Skip to content

Fix early USB security dongle branding detection; refine STATUS/NOTE/INFO logging, fix TPM sealing/counter increment & respawn loop#2094

Open
tlaurion wants to merge 8 commits intolinuxboot:masterfrom
tlaurion:detect_usb_security_dongle_branding_early
Open

Fix early USB security dongle branding detection; refine STATUS/NOTE/INFO logging, fix TPM sealing/counter increment & respawn loop#2094
tlaurion wants to merge 8 commits intolinuxboot:masterfrom
tlaurion:detect_usb_security_dongle_branding_early

Conversation

@tlaurion
Copy link
Copy Markdown
Collaborator

@tlaurion tlaurion commented Apr 28, 2026

Closes #2098
Closes #2097
Closes #2096 previouslly fixed in #2103

Summary

Multiple improvements for Heads initrd boot reliability: early USB dongle branding detection by VID, TPM sealing/counter-increment auth retry (TPM1 + TPM2), consistent STATUS/NOTE/INFO/DEBUG logging under /tmp/measuring_trace.log even in quiet mode, and BOOTSCRIPT respawn loop fix in case of DIE killing init.

Changes

1. USB Security Dongle Detection

  • Add sysfs VID polling loop (max 3s, 0.1s sleep, 30-iteration cap) for known dongle VIDs (20a0, 316d, 16d0, 1050) before lsusb branding detection — fixes Nitrokey 3 enumeration race
  • Fix PCR5 regression: don't auto-load USB modules in detect_usb_security_dongle_branding() — callers that need USB (HOTP/GPG/LUKS) must call enable_usb() first. Prevents unnecessary PCR5 extensions at boot that break DUK unseal on non-HOTP boards.
  • Add enable_usb at required call sites: GPG keyring init, HOTP verification, TPM reset flow

2. Logging Refinement

  • Rewrite doc/logging.md with clear INFO/NOTE/WARN/DEBUG usage guidance, table with sleep/blank-line columns
  • Add measuring_trace.log to Quiet mode table
  • Consistent STATUS/STATUS_OK usage across 15+ scripts (cbfs-init, gpg-gui, gui-init, kexec-*, lock_chip, network-init-recovery, oem-factory-reset, qubes-measure-luks, seal-hotpkey, seal-totp, tpmr, unseal-hotp, uefi-init, usb-init, gui_functions)
  • pcrs() formatting fix: filter sha256: header from TPM2 pcrread output
  • Recovery shell: show PCR state on entry

3. TPM Sealing & Counter Increment Fixes

TPM1:

  • Handle exit code 2 from tpm1_seal — QEMU TPM1.2 returns exit code 2 with empty stderr when NVRAM index doesn't exist. Fixed by capturing exit codes in subshells with set +e, checking both exit code and "illegal index" output.
  • Add _tpm1_auth_retry shared helper: re-prompts and retries up to 3 times on authorization failures, eliminating duplicate retry logic between counter create and increment
  • Add tpm1_counter_create, tpm1_counter_read, tpm1_counter_increment wrapper functions
  • Add tpm1_seal NVRAM define+write retry loop (consistent with tpm2_seal)

TPM2:

  • Fix regression from auth-retry rewrite — bare nvincrement (NV index auth) path was lost. Counters created by nvdefine default to empty NV index auth; nvincrement -C o was using owner hierarchy auth instead, causing TPM error 0x149 (AUTH_UNAVAILABLE).
  • Add 0x149 to grep patterns in tpm2_counter_inc and tpm2_counter_create retry logic
  • Document TPM2 error codes with reference to TCG TPM2 Part 2 (Structures) Table 18

4. DEBUG Traces at Boot Chain Decision Points

  • Add DEBUG before/after every decision point across init, gui-init.sh, key-init.sh, seal-hotpkey.sh, kexec-unseal-key.sh, kexec-boot.sh, functions.sh (preflight), and gui_functions.sh
  • Add TPM-reset-required marker flow: check_tpm_counterprompt_update_checksums targeted error message, update_totp menu bypass, show_tpm_totp_hotp_options_menu bypass
  • Handle "out of resources" (0x15) from TPM counter creation with targeted user guidance
  • Add doc/tpm.md and doc/ux-patterns.md

5. Respawn Loop Fix

  • Drop exec from cttyhack in init so the while true respawn loop actually respawns on boot script exit, instead of kernel panicking when PID 1 dies

Screenshots

TPM1 non-HOTP variant, normal boot (quiet mode)

Screenshot_20260501_124731

TPM2 HOTP variant, normal boot (quiet mode)

Screenshot_20260501_125053

TPM2 HOTP variant, normal boot (quiet mode) recovery shell access

Screenshot_20260501_125144

TPM2 HOTP variant, normal boot (quiet mode), less on advertised /tmp/measuring_trace.log

Screenshot_20260501_125317

Tested

  • qemu-coreboot-fbwhiptail-tpm2-hotp (full reset + re-ownership)
  • qemu-coreboot-fbwhiptail-tpm1-hotp (full reset + re-ownership)
  • x230-hotp-maximized, x230-maximized (TPM1)
  • v540tu (TPM2)

Copilot AI review requested due to automatic review settings April 28, 2026 21:54
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates initrd scripts to detect USB security dongle branding earlier and to refine console logging behavior (especially for quiet mode) by shifting messages among STATUS/STATUS_OK/NOTE/WARN and adding more explicit success milestones.

Changes:

  • Add an early sysfs-based wait in detect_usb_security_dongle_branding() to reduce mis-detection before lsusb is reliable.
  • Rebalance user-visible logging across multiple initrd scripts (more STATUS/STATUS_OK, convert some INFO→NOTE/WARN, add success confirmations).
  • Expand doc/logging.md to clarify intended semantics of INFO/NOTE/WARN and console behavior in quiet/info/debug modes.

Reviewed changes

Copilot reviewed 3 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
initrd/etc/gui_functions.sh Adjust integrity report output; add signing-key status messaging.
initrd/etc/functions.sh Add sysfs VID wait loop before lsusb branding detection.
initrd/bin/unseal-hotp.sh Add STATUS/STATUS_OK around TPM unseal of HOTP secret.
initrd/bin/tpmr.sh Change TPM2 unseal failure log level (INFO→WARN).
initrd/bin/seal-totp.sh Promote PCR-read logging to STATUS; show manual secret via NOTE.
initrd/bin/seal-hotpkey.sh Add STATUS/STATUS_OK around writing HOTP secret to dongle.
initrd/bin/oem-factory-reset.sh Add STATUS_OK milestones; adjust guidance output levels; fix TPM reset error handling block structure.
initrd/bin/network-init-recovery.sh Add STATUS_OK milestones for module load, clock sync, and SSH server start.
initrd/bin/lock_chip.sh Add STATUS_OK after chipset lock command.
initrd/bin/key-init.sh Reword ISO key loading messages and add final STATUS_OK.
initrd/bin/kexec-seal-key.sh Add STATUS_OK milestones for key generation, LUKS slot update, PCR reads.
initrd/bin/gui-init.sh Reduce/shift console output in reseal/TOTP/HOTP flows; add HOTP verification status lines.
initrd/bin/gpg-gui.sh Convert INFO instructions to NOTE.
initrd/bin/cbfs-init.sh Adjust SPI read messaging; add STATUS_OK on flash read success.
doc/logging.md Redefine INFO/NOTE positioning and document console styling/sleep/visibility matrix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread initrd/etc/gui_functions.sh Outdated
Comment thread initrd/etc/functions.sh Outdated
@tlaurion tlaurion force-pushed the detect_usb_security_dongle_branding_early branch from 9361484 to 2a485c5 Compare April 29, 2026 13:27
@tlaurion tlaurion marked this pull request as draft April 29, 2026 13:28
@tlaurion tlaurion requested a review from Copilot April 29, 2026 13:28
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 15 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread doc/logging.md Outdated
@tlaurion tlaurion force-pushed the detect_usb_security_dongle_branding_early branch from 2a485c5 to 5e09ef9 Compare April 29, 2026 13:57
@tlaurion tlaurion requested a review from Copilot April 29, 2026 13:59
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 15 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@tlaurion tlaurion force-pushed the detect_usb_security_dongle_branding_early branch from 5e09ef9 to c03366b Compare April 29, 2026 18:20
@tlaurion tlaurion requested a review from Copilot April 29, 2026 18:21
@tlaurion tlaurion changed the title Detect usb security dongle branding early, fixup STATUS STATUS_OK for quiet mode Detect usb security dongle branding early, fixup STATUS+STATUS_OK/INFO for quiet mode Apr 29, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 15 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread initrd/init Outdated
Comment thread doc/logging.md Outdated
@tlaurion tlaurion force-pushed the detect_usb_security_dongle_branding_early branch from c03366b to fee4251 Compare April 29, 2026 18:53
@tlaurion tlaurion requested a review from Copilot April 29, 2026 18:55
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 16 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread doc/logging.md Outdated
Comment thread initrd/init
Comment thread initrd/init Outdated
Comment thread initrd/init Outdated
Comment thread initrd/etc/functions.sh Outdated
@tlaurion tlaurion marked this pull request as ready for review April 29, 2026 19:04
@tlaurion tlaurion changed the title Detect usb security dongle branding early, fixup STATUS+STATUS_OK/INFO for quiet mode Refine STATUS/NOTE/INFO logging for consistent UX and accurate terminology Apr 29, 2026
@tlaurion tlaurion marked this pull request as draft April 29, 2026 19:08
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 23 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread doc/ux-patterns.md Outdated
Comment thread initrd/init Outdated
@tlaurion tlaurion force-pushed the detect_usb_security_dongle_branding_early branch from 90a7fa6 to 53811ff Compare May 2, 2026 14:23
@tlaurion tlaurion requested a review from Copilot May 2, 2026 14:27
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 23 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread initrd/init Outdated
@tlaurion tlaurion force-pushed the detect_usb_security_dongle_branding_early branch from 53811ff to 891cf0c Compare May 2, 2026 18:05
@tlaurion tlaurion requested a review from Copilot May 2, 2026 18:06
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 23 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread initrd/init Outdated
@tlaurion tlaurion force-pushed the detect_usb_security_dongle_branding_early branch from 891cf0c to 5047eb1 Compare May 2, 2026 21:03
@tlaurion tlaurion changed the title Improve USB dongle detection and refine STATUS/NOTE/INFO logging, fix tpm1 seal issue Improve USB dongle detection and refine STATUS/NOTE/INFO logging, fix tpm sealing/counter increment issue May 2, 2026
@tlaurion tlaurion changed the title Improve USB dongle detection and refine STATUS/NOTE/INFO logging, fix tpm sealing/counter increment issue Fix TPM2 counter increment, add DEBUG traces across boot chain, fix respawn loop May 2, 2026
@tlaurion tlaurion changed the title Fix TPM2 counter increment, add DEBUG traces across boot chain, fix respawn loop Fix early USB security dongle branding detection; refine STATUS/NOTE/INFO logging, fix TPM sealing/counter increment & respawn loop May 2, 2026
@tlaurion tlaurion requested a review from Copilot May 2, 2026 22:29
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 26 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread initrd/etc/gui_functions.sh Outdated
Comment thread initrd/init Outdated
@tlaurion
Copy link
Copy Markdown
Collaborator Author

tlaurion commented May 5, 2026

Splitted tpm1 issues in pr #2099 with refactoring to unify tpm1/tmp2 worflow. will rebase this pr once merged

@tlaurion tlaurion requested a review from Copilot May 6, 2026 23:55
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 26 changed files in this pull request and generated 3 comments.

Comment thread initrd/init Outdated
Comment thread initrd/etc/gui_functions.sh Outdated
Comment thread initrd/etc/functions.sh Outdated
tlaurion added 8 commits May 6, 2026 20:28
Delay branding detection until a known USB security dongle vendor ID appears in
sysfs, then run lsusb matching.

- Add bounded VID polling in detect_usb_security_dongle_branding()
- Keep branding fallback path when no known VID appears
- Initialize USB in integrity report path before branding detection

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Normalize user-visible logging across initrd scripts and documentation so output
levels are applied consistently.

- Align STATUS/STATUS_OK usage for action start and success
- Reserve NOTE for user guidance requiring attention
- Keep WARN/ERROR messaging actionable and consistent
- Update doc/logging.md to match runtime behavior

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Relative to origin/master (c2fb345):
- Introduces wait_for_usb_security_dongle_vid() with visible countdown.
- Adds user-cancel path during wait (keyboard/serial).

Current state:
- Wait exits early once a known VID appears.
- Wait times out after 15 seconds to avoid indefinite boot stall.
- Branding fallback path remains unchanged.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>

initrd/etc/functions.sh: harden recovery shell handoff

Relative to origin/master (c2fb345):
- Aligns pause_recovery() with hardened recovery checks.
- Drains serial input queue before launching recovery shell.

Current state:
- Buffered serial bytes are no longer interpreted as shell commands.
- PCR extension/auth path is preserved before shell handoff.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Relative to origin/master (c2fb345):
- Replaces asymmetric script handling with PID-tracked respawn loop.
- Tracks process ids per console path and restarts only when dead.

Current state:
- Main and auxiliary consoles respawn predictably without tight loops.
- Existing cttyhack/agetty split is preserved.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Relative to origin/master (c2fb345):
- Reintroduces DEBUG lines for critical startup branching decisions.
- Covers TPM/USB gating, recovery paths, and boot flow selection.

Current state:
- Early-boot decision points are observable in debug logs.
- Runtime behavior is unchanged; this is diagnostics-only.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Relative to origin/master (c2fb345):
- GIT_BRANCH-derived token used in artifact names is sanitized.
- Slashes/whitespace in branch names no longer create invalid output paths.

Current state:
- Artifact basenames remain traceable to branch context.
- Build copy/install steps no longer fail on branch names like feature/foo.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Correct DUK documentation from "128 characters" to "128 bytes" in runtime status/error messages and security/TPM docs. Add explicit notation of the brute-force space (2^1024) to clarify entropy magnitude.

The DUK is 128 bytes from /dev/urandom (1024 bits of entropy). Brute-force time grows exponentially with entropy: a 128-byte random secret has 2^1024 possible values, requiring an attacker to try about 2^1023 guesses on average.

Using the formula time ≈ 2^(H-1)/R (where H is entropy in bits, R is guesses/second):
- At 10^12 guesses/second, expected time is ~2^1023/10^12 seconds
- This is unimaginably longer than the age of the universe (~4×10^17 seconds)
- Every bit of entropy doubles the search space, making exponential growth the key property

For practical comparison: 80 Diceware words provide ~1032 bits of entropy, roughly comparable to 128 random bytes. Every attack rate is dominated by the exponential requirement.

Important caveat: this protection applies only to offline brute-force against a correctly stored secret. Online rate limits or poor storage would override these estimates.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>

initrd: address unresolved Copilot review feedback

Signed-off-by: Thierry Laurion <insurgo@riseup.net>

initrd: align dongle wait console output with logging policy

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
The squash lost the enable_usb call that initializes USB and triggers the
15-second dongle VID wait. This caused the wait to never execute when USB
wasn't pre-enabled at boot, breaking dongle detection on first boot.

Restore the unconditional enable_usb call followed by wait_for_usb_devices
only if USB wasn't previously enabled, matching the original flow.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 24 changed files in this pull request and generated 3 comments.

Comment thread initrd/etc/functions.sh
Comment on lines 610 to 613
# Child scripts can inherit DONGLE_BRAND while _USB_ENABLED resets, so always
# initialize USB unless the fast path above was taken.
enable_usb
[ "$usb_was_enabled" != "y" ] && wait_for_usb_devices
Comment thread initrd/etc/functions.sh
if [ "$is_serial" = "1" ]; then
STATUS "Waiting up to 15s for USB security dongle detection (press Enter to skip)"
else
STATUS "Waiting up to 15s for USB security dongle detection (press Esc to skip)"
Comment thread initrd/etc/functions.sh
Comment on lines +1094 to +1131
# Re-detect TTY so INPUT uses the correct device
detect_heads_tty

if [ "$CONFIG_TPM" = "y" ]; then
INFO "TPM: Extending PCR[4] with content of string 'recovery' to prevent further secret unsealing"
tpmr.sh extend -ix 4 -ic recovery
fi

gpg_auth

if [ -n "$*" ]; then
WARN "$*"
fi

if [ "$CONFIG_TPM" = "y" ]; then
INFO "TPM: PCR state on entering recovery shell:"
pcrs | while IFS= read -r line; do
INFO "$line"
done
fi

# Drain any queued serial input before starting the interactive shell.
# This avoids stale bytes being interpreted as bash commands on entry.
if [ -n "$RECOVERY_TTY" ]; then
while IFS= read -r -t 0 -n 1 _junk <"$RECOVERY_TTY" 2>/dev/null; do :; done
else
while IFS= read -r -t 0 -n 1 _junk 2>/dev/null; do :; done
fi

STATUS "Starting recovery shell"

if [ -n "$RECOVERY_TTY" ]; then
setsid /bin/bash <>"$RECOVERY_TTY" >&0 2>&0
elif [ -x /bin/setsid ]; then
/bin/setsid -c /bin/bash
else
/bin/bash
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants