Provide tpmr unseal to unseal a file with TPM1 or TPM2. For TPM1, it
wraps tpm nv_readvalue and tpm unsealfile. For TPM2, it wraps tpm2
unseal.
kexec-unseal-key, seal-hotpkey, unseal-hotp, and unseal-totp no longer
need to differentiate TPM1/TPM2.
Fixes spurious shred errors on TPM2 that only apply to TPM1 (temporary
sealed secret file and shred are now internal to tpmr).
Fixes TPM1 disk unlock key unsealing due to logic errors relating to
exit status of tpmr unseal or tpm unsealfile (now always uses status of
tpmr unseal).
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
TPM2 locks the platform heirarchy, flushes transient objects, and
flushes sessions. (This now cleans up sessions created during
startsession that previously were not cleaned up, although the OS might
flush all sessions as well.)
TPM1 currently does not do anything, but the command is accepted so
kexec-boot does not need to differentiate TPM1/2.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
TPM2 is only required to support password lengths up to its longest
hash size (32 chars for sha256). Pass the sha256 of the password
instead of the actual password so the password can be arbitrarily long.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Set flags 'fixedtpm|fixedparent|adminwithpolicy'. Plain password auth
is no longer allowed. For objects sealed with a password, the password
is part of the auth policy, so both PCRs and password must be satisfied
to unseal.
Tested by manually attempting to unseal disk unlock key with password:
tpm2 unseal -c 0x81000003 -p "<password>"
This now correctly returns an error indicating this auth method is not
allowed.
Relative to the documented default flags for tpm2_create:
* sign, decrypt: Not applicable to a sealed object, tpm2_create
automatically removed these from the defaults.
* fixedtpm, fixedparent: Kept
* sensitivedataorigin: Not applicable an object where the sensitive
data is not generated by the TPM.
* userwithauth: Removed this, "user" actions must satisfy auth policy.
* adminwithpolicy: Added this, "admin" actions must satisfy auth
policy.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
After saving a disk unlock key, if debug output is enabled, drop to
a recovery shell to allow inspection of debug output.
The script isn't intended to return from this point after sealing a
key - returning attempts to boot, which can't unseal the key.
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>
When sealing/unsealing with a password, use a policy including both the
specified PCRs and the object password. Fixes sealing and unsealing
disk unlock key.
tpm2 seems to have a bug in parameter decryption when using a policy
session and password in this way, disable encryption in the policy
session as a workaround.
Flags still need to be set on the sealed object correctly, as the
password is normally allowed on its own as an alternative to policy
auth.
Add -Q to some tpm2 invocations to silence diagnostics on stdout.
Pass filename for unsealed secret rather than capturing from stdout
for robustness against tpm2 diagnostics on stdout.
Fix unseal result check in kexec-unseal-key.
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
Always send password via stdin to tpm2 create, tpm2 unseal. The password
could being with things like 'file:', 'str:', 'pcr:' that would be
interpreted by tpm2.
Deduplicate the TPM1/2 code in kexec-unseal-key. The TPM2 code was not
actually prompting for the password or sending it to tpmr unseal.
Password is still not working yet though.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
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>
Use common password prompt logic in tpm-reset rather than duplicating
in tpmr reset.
Use common logic in config-gui.sh to reset the TPM.
Use common logic in oem-factory-reset to reset TPM. Fixes extra
prompts for TPM2 owner password even when choosing to use a common
password. Fix sense of "NO TPM" check in TOTP generation (which only
happened to work because CONFIG_TPM is empty for TPM2).
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
$CONFIG_TPM needs to be quoted, or [ syntax is incorrect when it's
empty. Fixes errors in console with TPM2 (but behavior was correct due
to [ still returning false as expected).
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Resetting the TPM creates a new primary object, and there is no reason
for kexec-save-default to sign an old hash. Always update the hash
instead of creating it only if it doesn't exist.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Resetting the TPM invalidates the primary handle hash, and
kexec-save-default only generates a hash if none exists. Remove the
hash file when it is invalidated.
OEM reset and "Reset Configuration" both already remove all kexec
files.
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
- kexec-save-default extracts initrd crypttab files and creates /boot/kexec_initrd_crypttab_overrides.txt entries pointing to /secret.key
- kexec-insert-key applies /boot/kexec_initrd_crypttab_overrides.txt to replace initrd's crypttabs files pointing to inserted /secret.key through cpio
- Both scripts inform the user of applied magic on screen
Not all distro put crypttab under /etc/ within initramfs, but finding it at
runtime needs unpacking, which may be hard to do, so it is made overridable
with a file at /boot/kexec_initrd_crypttab_path.txt, whose content could be
obtained with $ cpio -t < ${uncompressed_initrd} | grep crypttab .
The "target" field of the record within the crypttab stored in the root
file system for the luks container which is going to be unlocked via
kexec-insert-key should be modified into the same "luks-$uuid" format,
otherwise the boot sequence will get stuck when OS is trying to unlock them
again, in order to map them according to "target" fields written in the
crypttab stored in the root fs.
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.
If the user selects "continue to main menu" from an error, do not show
any more error prompts until reaching the main menu.
We still try to initialize everything (GPG, TOTP, HOTP) so that the
main menu can still show TOTP/HOTP if GPG is not configured, etc., but
no more prompts are shown after selecting "continue to main menu".
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
A lot of echo_entry() is now common to elf/multiboot/xen kernels, just
branch for the type-specific logic.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
If a boot option doesn't refer to a valid file for the kernel/initrd,
ignore it. Such an option is never bootable, because we would fail to
find the kernel/initrd. This could happen if the path contained GRUB
variables, or specified a device that wasn't /boot, etc.
This is checked before expanding GRUB variables. It's unlikely that
any kernel/initrd path containing variables would end up working when
all variables expand to nothing (since we do not handle GRUB
variables).
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
Some configs specify kernel/initrd paths relative to a device (often
found in a variable). Assume the device is the /boot partition and
ignore the device specification.
Signed-off-by: Jonathon Hall <jonathon.hall@puri.sm>
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>
- Have Talos II supported by detecting correctly size of mtd chip (not internal: different flashrom output needs to be parsed for chip size)
- Read SPI content only once: 66% speedup (TOCTOU? Don't think so, nothing should happen in parallel when flashing insingle user mode)
- Have the main flash_progress loop not break, but break in flash_rom state subcases (otherwise, verifying step was breaking)
- Change "Initializing internal Flash Programmer" -> "Initializing Flash Programmer"
- Apply changes suggested by @SergiiDmytruk under https://github.com/osresearch/heads/pull/1230#issuecomment-1295332539 to reduce userland wasted time processing flashrom -V output
EC signatures requires that the digest has the corresponding length. Removing the hardcoded sha2-256 hash function and adding support of sha2-384 and sha2-512 should allow using EC crypto.
- Take System Info changes from 06311ff068 (Thanks to @nestire)
- Move changes to seperate script under /bin/oem-system-info-xx30
- Add additional camera and wifi card IDs, add synaptic touchpad detection if kernel has module built in
Above changes squashed in this commit.
Since /etc/luks-functions are currently exporting passphrases tested good per cryptsetup to be reused in the code,
the logic calling both luks_reencrypt and luks_change_passphrase testing for non-empty luks_current_Disk_Recovery_Key_passphrase
was bogus.
This commit includes a new variable luks_new_Disk_Recovery_Key_desired which is set when reencryption is desired.
The 3 use cases (reencrypt+passphrase change, reencrypt no passphrase change and passphrase change alone now only test
for luks_new_Disk_Recovery_Key_desired and luks_new_Disk_Recovery_Key_passphrase_desired, nothing else.
network-init-reovery can be used to automatically set RTC clock to obtained NTP clock.
The script would fail if other devices devices previously registered on the network with the same MAC.
Consequently, maximized boards are detected here, and a full random MAC is generated and used instead of using hardcoded DE:AD:C0:FF:EE.
This continues to generate checksums and sign them per new GPG User PIN, but does not set a default boot option.
The user hitting Default Boot on reboot will go through having to setup a new boot default, which will ask him to setup a Disk Unlock Key if desired.
Otherwise, hitting Default Boot goes into asking the user for its Disk Recovery Key passphrase, and requires to manually setup a default boot option.
Simplify the menu options by removing the duplication of the entry name
in the menu selections; instead, use clear verbiage to distinish
between booting one time and making the default. And as the majority of
the boot menu is shown is when the grub entires have changed and the
user is prompted to select a new default, so make that the first/default
menu option.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Drop the duplicated kernel info which hurts readability, runs off the
end of the menu window. This also makes it easier to identify which
menu option is the default, and more closely resembles the grub menu
shown in a traditional BIOS boot.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
- initrd/bin/oem-factory-reset: adds a measured integrity output prior of prompts. Goal is for stating TOTP/HOTP/boot detached signed measurements prior of initiating a Re-Ownership, validating provisioned OEM state.
- initrd/bin/gui-init : Add two additional menu options to LUKS reencrypt and LUKS passphrase change, calling functions of initrd/bin/reencrypt-luks
- initrd/bin/gui-init : Add option F for EOM Factory Reset / Reownership when no public key is exported by key-init
oem-factory-reset: adapt code so that custom passphrases can be provided by user without changing oem factory reset workflow.
oem-factory-reset: output provisioned secrets on screen at the end of of the process.
oem-factory-reset: warn user of what security components will be provisioned with defaults/customs PINs prior of choosing not after
gui-init and oem-factory-reset: change OEM Factory Reset -> OEM Factory Reset / Re-Ownership to cover actual use cases
It is going to be enabled later anyway (if CONFIG_HOTPKEY=y), so it can
also be simplified by enabling it at the very beginning.
This enables USB keyboard consistently during all boot menus, including
the "No Bootable OS Found" prompt. It isn't a big deal for "normal"
laptop usage, but it is important for automatic tests and also
non-laptop systems.
Show state of flashrom reads/writes by means of a progress bar,
as used in the Librem coreboot flashing scripts
v2: add adjustment for use with `--ifd`
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
-CircleCI addition.
-Removal of t530-flash, w530-flash boards, flash scripts and associated coreboot configs (no more legacy boards additions)
This is a merger of #1071, #1072 and #1073 so that test builds are available over CircleCI until osresearch/master CircleCI gets unlocked.
When files in /boot fail hash verification, the list of files
can sometimes overflow the whiptail msgbox, preventing the
prompt and buttons to update checksums from showing. To mitigate
this, if # of files is > 10, use less to show the file list and
present a separate prompt to update the checksums once the file
list has been viewed.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
- Fixed inversed HEIGHT and WIDTH usage
- Fixed height to 30 and width to 90 as everywhere else
This was causing a blank screen when whiptail without framebuffer (fbwhiptail) was used.
Actually, it seems like the width and height under whiptail calls are only taken into consideration under NEWT, not FBWHIPTAIL.
copy/paste error resulted in user-entered comment never
being set/checked/used, and email address being overwritten.
Fix variable usage so comment and email are set correctly.
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>
After updating/flashing a new ROM, a new TOTP secret must be generated,
but the $TOTP variable needs to be updated afterwards, otherwise it
will show the previous failure which led to the new secret being
created.
Fix this by re-calling update_totp() after generating a new secret
or resetting the TPM.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
If user selects to manually update the TOTP via the menu,
we should do it regardless of elapsed time from previous
check. Otherwise, HOTP will be checked regardless of validity
of TOTP.
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>
Currently, if no disks on system, selection of a new /boot
device will silently fail and simply return the user to the
previous screen. Add an error dialog if no disks found.
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>
Checking the keyring for a GPG and updating the TOTP/HTOP
status need only happen once at initial boot; the latter
can be updated at any later time from the main menu itself.
Having them repeated each loop of the main menu is unnecessary
(and often annoying). Likewise, the default auto boot can be
moved and the first_pass (and unused MAIN_MENU_OPTIONS)
variable dropped.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Now that all menu options are encapsulated in shell
functions, move menu handling from the main loop to
inside the menu/submenu function itself.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Break menus and menu items into functions where possible.
Improves readability of code / functional flow, and
makes future refactoring easier.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Name better reflects function purpose, allows 'update_totp'
to be used to actually update the TOTP code.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
strings from $cmdremove should only be removed from $cmdline if they are enclosed by spaces of if they are at the beginning of $cmdline followed by a space or if they are at the end of $cmdline prepended by a space
if CONFIG_AUTO_BOOT_TIMEOUT exists and is set, and if HOTP
validation was successful, then attempt to boot the default
target after CONFIG_AUTO_BOOT_TIMEOUT seconds if not interrupted
by key press
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
The -u arg does not take a parameter, so remove the trailing colon.
Fixes /boot hashes not being updated when update_checksums() is called.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
If an installed OS is not detected, then skip setting the
default boot device or generating /boot checksums.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Check for presence of CONFIG_BOOT_DEV, and if missing or
unable to be mounted, present the user with a menu offering the
option to select another disk, boot from USB, continue to
main menu, or drop to a recovery shell.
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>
Strip the path prefix from the ROM filename, and place on own
line to prevent truncation with long filenames / narrow screens.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
This will allow it to be used elsewhere within the UI.
Rename CONFIG_BOOT_GUI_MENU_NAME to better indicate use/function.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
* modules/coreboot: add option to use coreboot 4.11
Port patches from coreboot 4.8.1 to 4.11:
* 0000-measure-boot -> 0001
* 0010-cross-compiler-support
All other patches for coreboot 4.8.1 have either already been
integrated, or are for platforms which do not need to be migrated
to coreboot 4.11 (they will move to 4.12 or newer).
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
* patches/coreboot-4.11: Add Broadwell-DE platform patch
Add a patch for FSP Broadwell-DE to make use of Heads' measured boot.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
* patches/coreboot-4.11: Add patch to read serial # from CBFS
Will be used by multiple Librem boards.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
* patches/coreboot-4.11: add board support for Librem Server L1UM
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
* Librem Server L1UM: add new board
Add board config, coreboot config, kernel config files.
Add conditional purism-blobs dependency to coreboot-4.11 module.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
* flash.sh: add special handling for librem_l1um board
Add support for persisting PCIe config via PCHSTRP9 in flash descriptor.
This is needed to support multiple variants of the L1UM server which
use the same firmware but differ in PCIe lane configuration via the
PCH straps configuration in the flash descriptor.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
* patches/coreboot-4.11: Add 'Use PRIxPTR to print uintptr_t' patch
Cherry-picked from upstream coreboot (post-4.11), fixes compilation issue.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
* CircleCI: add target to build board librem_l1um
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.
Changing the default boot was failing because remove the old entries did
not work as `rm "/some/path/*.txt"` does not work as intended, e.g. the
asterisk is no catch-all.
Some grub configs/bls entries contain the full paths to the
kernel/initrd files, which the parsers currently fail to handle,
causing a failed boot without any useful error being presented to the user.
To fix this, strip the bootdir prefix from the menu entries when parsing,
should it exist.
Test: build/boot Librem 13v2 w/F32 and bls entries containing absolute paths.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
When a new /boot device is selected, wait until after
successfully mounting the newly-selected device before
updating CONFIG_BOOT_DEV.
Also, don't assume /boot already mounted, as this can cause
a false failure and prevent mounting of the newly-selected device.
Lastly, tidy up the error output in case mounting /boot fails.
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>
Attempting to reset the TPM when once isn't present causes a kernel
panic, so let's not allow users to do that.
Test: verify 'No TPM Detected' shown on Librem Mini when Reset TPM
option selected from menu.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
-r will always succeed since the file will be generated regardless
of number of boot entries found. Use -s instead to check for zero
file size.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Since we sort the boot options prior to selecting the new default entry,
we need to use the index of the entry in the list prior to being sorted,
vs always setting it as 1. This fixes setting/booting of the default
OS target where the list entries are changed when calling sort.
Test: perform OEM factory reset with Fedora 32 installed, verify
default boot succeeds followng reset.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
The same grub parsing logic used in kexec-select-boot should
be used here as well, so copy it over.
Test: oem-factory-reset succeeds with Fedora 32 installed.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
With current implementation, Librem Keys with VID 0x316d are
not identified properly; correct the if/else logic to resolve.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Add a linebreak before showing list of files with changed
checksums. Fix text truncation on checksum update prompt.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Adjust text on GUI dialogs to prevent filenames from being truncated
and to improve clarity/readability.
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>
Show RAM in GB, since the calculation in MB is imprecise as
it excludes RAM allocated for GPU (eg).
Fix display of firmware version strings which contain spaces by
adjusting cut and simply chopping off the date at the end, which
is a fixed 10-char length.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Since #758 is merged, users have a option to export GnuPG pubkey if
necessary. Thus, we they do not need to insert a USB drive during
factory reset. Until now the whole process failed just because a user
did not provide a USB drive instead.
This shall be fixed by this commit
If smartcard Nitrokey Storage was factory-reset, we delete AES keys on
it as well.
Explaination: After oem-factory-reset was started the AES on the Nitrokey Storage that is used for the encrypted volume and the password safe is is not usable anymore because the smart card was factory-reset. To make it usable, a user needs to delete it via Nitrokey App. By doing so, the HOTP secret is deleted as well, resulting in a bad warning in Heads. Therefore, we are resetting AES key right after factory-reset with hotp_verification
Add CONFIG_TPM_NO_LUKS_DISK_UNLOCK to allow Librem boards to opt
out of using TPM to store LUKS key, and use it to guard the user
option to add the disk encryption key to the TPM.
Select this option for all Librem boards; all other boards which
select CONFIG_TPM=y will have no change in functionality.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Rather than wait a fixed 5s for the usb storage kernel modules
to load, and the user to insert a drive, check for new USB drives
inserted every 1s with a 5s timeout.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
mount-usb switched to dynamic USB device detection a while back,
so eliminate instances of CONFIG_BOOT_USB_DEV, and derive the
mounted USB device from /etc/mtab in the one place where it's
actually needed (usb-scan). Clean up areas around calls to
mount-usb for clarity/readability.
Addresses issue #673
Test: Build Librem 13v4, boot ISO file on USB
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Commit 6b5adcca moved the call to enable_usb from gui-init
to init and guarded it with CONFIG_USB_KEYBOARD, but it was
missed that this is needed for the clean boot check logic
when a librem key is used. Add the call back to gui-init
and guard it properly
Test: clean_boot_detect works properly on a librem 13v4
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Some (out of tree) servers require use of a USB keyboard, and need
the USB kernel modules loaded prior to checking for keypress to enter
a recovery console. Since loading the modules affects the value in PRC5
and can cause issues putting a LUKS key in TPM, guard the loading of the
USB modules with CONFIG_USB_KEYBOARD and remove the unguarded call from
gui-init.
This should resolve issues #603 and #674.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Not setting USB_FAILED when call to mount-usb succeeds results
in a spurious 'sh: 0 unknown operand' error printed to console.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Since the custom password is used to set the GPG admin
password as well as the TPM and GPG user passwords, an
8-character minimum is required. Inform the user of this,
and validate custom password length upon entry.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
If /boot isn't mounted, we can't read the HOTP counter, so no
point in reading from the TPM. This speeds up getting to the
main menu in the case of an inaccessible or non-existant /boot.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Update text on TOTP error prompt to provide better
guidance for users following the use of the OEM
factory reset function
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Normally we resort to default passwords for OEM reset, however we have a
use case where it would be convenient to set a custom password instead.
This patch adds a simple prompt (that defaults to the defaults if you
hit Enter) that enables someone using the OEM reset to enter a single
password that will replace the defaults (TPM, GPG Admin, GPG User).
If the user chooses to flash a "cleaned" ROM (not persisting settings
or GPG keys) then the signatures on /boot are no longer valid, so clear
them out. This allows for the OEM factory reset prompt to be shown on
the next boot.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Users may wish to temporarily boot an OS from a drive other than
their primary boot drive, without changing the default and saving
to ROM. Mounting /boot after changing the device selection
facilitates this by allowing the user to then choose an unsafe boot
from the newly-selected boot drive.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
when commit [928f003] config-gui: add 'Full Reset' option
was added, the bottom end of the save config option was
accidentally truncated; restore it to fix save config option
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Add a check to determine if first boot after flashing a cleaned
ROM, and prompt user to run the OEM Factory Reset if so
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Add an OEM Factory Reset menu option, which performs an
unattended reset and configuration of the device's TPM,
GPG security token, and boot device / boot selection.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Add oem-factory-reset script which performs an unattended
reset and configuration of the device's TPM, GPG security token,
and boot device / boot selection.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Next prompt will be to ensure GPG key is attached, which defaults
to Y, so default here as well for consistency
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Check that any files added to cbfs exist before attempting to
add them, so flashing doesn't fail after a reset.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Add Full Reset option to clear all GPG keys and user settings,
both from the local filesystem and running firmware, and
clear/reset the TPM
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
If the boot device is invalid or unabled to be mounted
and the user opts to select a new boot device, jump
directly to that menu option and avoid the additional
step of showing the config main menu.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Updating TOTP/HOTP is mainly necessary after a user updates
their firmware, and no need to force another reboot.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
use similar filtering logic as with USB drives to provide
the user a more sane list of boot device options. Show user
only valid bootable partitions, not block devices.
There's no point in showing /dev/nvme0 and /dev/nvme0n1 (eg)
when /dev/nvme0n1p[1..n] (eg) exist, as the former are not
valid boot devices.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Add optional parameter to bypass menu selection and
immediately select a menu option. This allows us to call
the 'Set Boot Device' option directly, saving the user
an unnecessary step.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Introduce option to remove any existing key(s) from firmware
and add a user-suppled key, before reflashing.
Move existing code for adding a new key to a separate function
so it can be reused for new feature without duplication.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
If CONFIG_BOOT_DEV isn't set or otherwise fails to mount,
we prompt the user to change the /boot device, but never
attempt to mount it to ensure it's sane, leading to
potential failures later in the config/boot process.
Ensure that CONFIG_BOOT_DEV is updated after the /boot device
is changed, and attempt to re-mount /boot after the change.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
If the user has changed the /boot config but not yet flashed,
it's reasonable for them to expect that flashing to add/update
a GPG key won't revert those changes.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
In order to streamline the initial setup, prompt user to
update checksums/sign /boot files after adding a key and
updating the firmware, in order to avoid an extra reboot.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Move the non-GUI component of update_checksums() to
/etc/functions so it can be reused outside of gui-init.
Add check that /boot/kexec_default_hashes.txt exists before parsing
it, since doesn't exist if there's no default boot target set yet.
Eliminates spurious error text and/or premature exit depending on
state of errexit.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
'Options' makes more sense than 'Settings' given the submenu's contents.
Tidy up Boot Options as well
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Before anything else, ensure that a default boot device
is set. If not, prompt the user to set one. If set, ensure
that /boot can be mounted successfully; else prompt the
user to select a new boot device.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
If /boot isn't mounted, we can't read the HOTP secret, so no
point in reading from the TPM. This speeds up getting to the
main menu in the case of an inaccessible or non-existant /boot,
and maintains the warning condition from not being able to
validate the HOTP.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Since a USB boot target can't be the default (at least currently,
/boot must be on internal media), skip the extraneous prompt to
set it as such when booting from USB.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Exclude dot folders from ROM search path, so that files in
.Trash (eg) aren't shown. Sort the remaining options.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Using sort on USB boot options produces a reverse-ordered list,
leading users to often select the wrong option. Add the -r
parameter to sort to correct the list order and make the default
option the first in the list.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Because of the way unseal-hotp is called from gui-init,
dropping to a recovery shell when failing to mount /boot
causes it to hang, leaving the user stranded until they
kill it with CTRL+C. Instead, simply return and continue
to the main GUI menu where the user can address the problem.
Rename the function to clarify difference from other versions
of mount_boot() which do drop to the recovery shell.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Fix HOTP verfication failure if LK admin pin/passphrase contains
spaces by quoting the variables when passed to functions.
Test: set LK admin pin to passphrase with spaces, generate
new TOTP/HOTP, verification passes.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Reading the file into a variable and then redirecting to stdin
via echo() can cause the binary data to be truncated, leading
to an invalid base32 value and failure to properly generate
and validate the HOTP code.
To resolve this, pass the file directly to hotp(), and ensure
it is removed properly regardless of success or failure to
prevent leakage.
Fixes "Invalid base32 string" error seen when attempting to
generate a new TOTP secret.
Signed-off-by: Matt DeVillier <matt.devillier@puri.sm>
Add a main boot menu entry to power off. This enables users to
only verify the firmware integrity using OTP, and do nothing more.
After having left the device out of sight, one might want to do
a quick sanity check only.
Since we already have a script to safely power down, we make use of
it now.
Instead of relying on a hard-coded USB disk, it would be better if the
mount script attempted to dynamically detect available USB disks. This
modification to the USB mount script attempts to handle the common case
of a single USB disk but can also handle the case of multiple disks
where it will present the user with all available USB disks
This mimics tlauion's OEM work in the sense that a user (or OEM) could
choose this option and it will reset an OpenPGP smart card and
automatically generate a random key on it. The idea is to allow an OEM
to set up a Librem Key and Heads on a machine before shipping with a
random key, so the user can test for tampering when they receive the
machine, and then the user can choose to reset all of the keys with
their chosen keys after that fact.
Currently Heads relies on a hard-coded config value to determine which
USB disk to mount. This can be problematic when trying to distribute a
pre-built version of Heads that can work on multiple disk
configurations. I've modified the USB mounting script so that it
attempts to detect all USB boot disks present on the system, pick sane
defaults, and prompt the user when there are multiple choices.
I've also removed the USB configuration option from config-gui.sh as
this config option is no longer used.
This change updates the very basic GPG smartcard feature in the GPG GUI
so that it can properly support generating a key from within Heads. It
offers the user the option to copy the generated GPG public key to a USB
thumb drive so it's not lost as well as the option to reflash the
current Heads BIOS with this new public key added to the keyring.
I've moved the common functions required to flash a new ROM with GPG
changes into a shared function at the top of the script.
It makes more logical sense for GPG functions to be split out into their
own menu instead of being part of the "Flash" menu. This creates a
gpg-gui.sh script and moves GPG options there while adding a few
additional features (like listing keys and initial smartcard key
generation support).
key-init makes sure trustdb is updated at run time and user and distro keys are ultimately trusted. Each time a file is signed, the related public key is showed without error on it's trustability.
flash-gui deals with gpg1 to gpg2 migration. If pubring.kbx is found, pubring.gpg is deleted from running rom dump.
.ash_history: add examples to generate keys and otrust in rom
flash-gui: export otrust and import it in rom
key-init: import otrust.txt if present to supress warning about user public key being untrusted
We need to handle the case where the specific config file doesn't exist,
or else grep fails, so we touch the file ahead of time. Mounting the usb
storage caused problems when you re-enter the menu a second time, so we
will just load the storage module.
As part of the config gui we want to be able to have the system define
new config options without them being lost if the user makes their own
changes in CBFS. To allow that this change creates a function initiated
in init that combines all /etc/config* files into /tmp/config. All
existing scripts have been changed to source /tmp/config instead of
/etc/config. The config-gui.sh script now uses /etc/config.user to hold
user configuration options but the combine_configs function will allow
that to expand as others want to split configuration out further.
As it stands here are the current config files:
/etc/config -- Compiled-in configuration options
/etc/config.user -- User preferences that override /etc/config
/tmp/config -- Running config referenced by the BIOS, combination
of existing configs
This change will add a new GUI script that will allow users to change
their running configuration (currently just /boot and USB boot options)
and optionally persist that modified configuration with reflashing the
BIOS with a modified cbfs.
The Librem coreboot is labeled with the current version and is visible
from dmidecode and is supposed to reflect the current version of
coreboot, however it was out of date and reflected 4.7 when Heads has
moved on to 4.8.1.
I've also added a simple change to further simplify onboarding by
warning users who have Librem Key configured when they boot without it
being inserted.
We want to catch the missing GPG keyring error regardless of TPM failure
or even in the case of a system without a TPM at all so we need to move
that section up above the TPM check.
To help with onboarding new users to Heads, this change will detect when
Heads does not have any keys in its keyring and will guide the user
through adding a key to the running BIOS. It's important that this
happen *before* guiding them through setting up an initial TOTP/HOTP
secret because adding a GPG key changes the BIOS, so the user would have
to generate TOTP/HOTP secrets 2x unless we handle the keyring case
first.
In addition to this change I've simplified the main menu so that the
majority of the options appear under an 'advanced' menu.
When the Librem Key is enabled, the kernel loads USB modules at boot,
this causes PCR5 to change and breaks unsealing the LUKS key (if set).
This change retains the protection of the PCR5 check unless Librem Key
is enabled.
Granted the user should really be using the Librem Key/phone to check
for tampering (since an attacker could control the Heads background
color) but this provides another visual queue for the user with
the GUI menu to catch less sophisticated tampering.
The HOTP counter isn't a secret but is just used to prevent replay
attacks (the time-based counter in TOTP isn't a secret either) so it
doesn't need to be protected in the TPM and storing it as a TPM
monotonic counter was causing conflicts with the Heads configuration
counter as TPM 1.2 can only increment one counter per reboot.
This change moves the HOTP counter into the file in /boot that was
previously keeping track of the TPM counter id.
TPM v1.2 has a limitation in that only a single monotonic counter can be
incremented between reboots [1]. So in the event we are using HOTP
monotonic counters, we need to reference those for the Heads rollback
counter when we update file signatures in /boot, otherwise the increment
stage at kexec-sign-config will fail since at each boot, the HOTP
monotonic counter has already been incremented.
[1] https://projects.csail.mit.edu/tc/tpmj/UsersGuide.html#inccounter
The Librem Key is a custom device USB-based security token Nitrokey is
producing for Purism and among other things it has custom firmware
created for use with Heads. In particular, when a board is configured
with CONFIG_LIBREMKEY, this custom firmware allows Heads to use the
sealed TOTP secret to also send an HOTP authentication to the Librem
Key. If the HOTP code is successful, the Librem Key will blink a green
LED, if unsuccessful it will blink red, thereby informing the user that
Heads has been tampered with without requiring them to use a phone to
validate the TOTP secret.
Heads will still use and show the TOTP secret, in case the user wants to
validate both codes (in case the Librem Key was lost or is no longer
trusted). It will also show the result of the HOTP verification (but not
the code itself), even though the user should trust only what the Librem
Key displays, so the user can confirm that both the device and Heads are
in sync. If HOTP is enabled, Heads will maintain a new TPM counter
separate from the Heads TPM counter that will increment each time HOTP
codes are checked.
This change also modifies the routines that update TOTP so that if
the Librem Key executables are present it will also update HOTP codes
and synchronize them with a Librem Key.
In addition to being able to flash a ROM from the GUI, it would also be
useful for a user to be able to add a GPG key to their keyring using the
flashing tool. This change adds the ability for a user to edit both a
ROM located on a USB key and also edit the running BIOS by using
flashrom to make a local copy of the running BIOS, edit it, then reflash
it. This also supports the upcoming delete feature in CBFS for
circumstances where keyring files already exist within CBFS.
If we want to modify a running BIOS we will need the ability to pull
down the current BIOS, modify it, and then reflash. This change adds a
read option to flash.sh and pulls down three versions of the BIOS and
only exists successfully if all three match.
To keep the flash logic simpler the GUI logic has been split into a
flash-gui.sh program so flash.sh behaves closer to the original flashrom
scripts it was based from. I've also removed the previous flashrom
scripts and incorporated their options into flash.sh. Finally I set
CONFIG_BOARD via the Makefile instead of setting a duplicate option in
each board's config.
Based on the conversation for PR #406, we decided to go with a more
generic script for general-purpose flashing instead of having individual
(and therefore very similar) flash scripts for each board type. This
script currently handles flashrom on Librem and X230 board types and
introduces a new CONFIG_BOARD option that sets specific flashrom
arguments based on the board.
It also adds support to gui-init to call this flash script.