Skip to content

initrd/gpg: add reprovision smartcard from GPG key backup flow - #2158

Draft
tlaurion wants to merge 9 commits into
linuxboot:masterfrom
tlaurion:reprovision-smartcard-from-backup
Draft

initrd/gpg: add reprovision smartcard from GPG key backup flow#2158
tlaurion wants to merge 9 commits into
linuxboot:masterfrom
tlaurion:reprovision-smartcard-from-backup

Conversation

@tlaurion

@tlaurion tlaurion commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator
  • Add gpg_card_factory_reset() shared function for factory-reset + forcesig + key-attr setting (RSA and ECC/P-256), extracted from oem-factory-reset.sh with explicit --passphrase-file support
  • Add gpg_keytocard_subkeys() shared function: enable USB, verify card, move subkeys to slots 1-3 (sign, encrypt, auth)
  • Add gpg_set_card_identity() shared function for cardholder name and login fields with explicit admin PIN
  • Add gpg_reset_nk3_secret_app() shared function for Nitrokey 3 Secrets app reset, parameterized on admin PIN
  • Replace oem-factory-reset.sh function bodies with thin wrappers that call the shared gpg_* functions via positional args
  • Add reprovision_smartcard_from_backup(): 10-phase flow that mounts the LUKS backup, detects key type from imported key, mounts public partition, factory-resets card, restores subkeys, sets identity, offers ROM flash
  • Add k option to GPG Management Menu (gpg-gui.sh), always visible
  • Add K option in prompt_missing_gpg_key_action (gui-init.sh)
  • Add clean boot wizard offering OEM reset, reprovision, or ignore
  • Update doc/gpg.md, doc/configuring-keys.md, doc/architecture.md for the new recovery path
  • Document QEMU testing workflow and hardlink preservation pattern in doc/qemu.md (USB flash drive workflow + reprovision test)
  • Add Authentication and Resetting Configuration sections to doc/recovery-shell.md

Extends PR #1515 (2023): authentication via gpg_auth can now be enforced with key material restored from a backup, allowing recovery shell/USB boot access control even after dongle replacement.

Tested on real hw with

  • Nitrokey 3: OEM factory reset creates LUKS backup + provisions dongle successfully.
  • Nitrokey Pro 2: reprovision from backup restores subkeys to (new) dongle, PIN changes, public key import, ROM flash, and gpg_auth works after reboot.
  • Config wipe from Options menu correctly triggers clean boot wizard with OEM/reprovision/ignore choice.
  • qemu with canokey

For the sake of this test, as per doc/qemu.md guidelines, on host

./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2-prod_quiet
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2-prod_quiet run

Workflow

Restore key material backup from prior OEM factory reset/ Re-Ownership having creating such backup

Simulation: wipe cakokey
sudo rm build/x86/qemu-coreboot-fbwhiptail-tpm2-prod_quiet/.canokey-file
Let's reprovisioning of key material backup
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2-prod_quiet run
Screenshot_20260714_143332
Screenshot_20260714_143413
Screenshot_20260714_143430
Screenshot_20260714_143434
Screenshot_20260714_143507
Screenshot_20260714_143515

Again a qemu consideration, but to truely simulate enabled authentication, and because qemu cannot inject things in firmware, one have to switch the feature on in board config (not on real hardware):

#Enable HAVE_GPG_KEY_BACKUP to test GPG key backup drive (we cannot inject config under QEMU (no internal flashing))
export CONFIG_HAVE_GPG_KEY_BACKUP=y

And then final test, after resealing etc on reboot per firmware changes:
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2-prod_quiet PUBKEY_ASC=pubkey.asc inject_gpg run

Accessing Recovery Shell, authenticating with key material backup on thumb drive signature test:

Screenshot_20260714_144210 Screenshot_20260714_144429

Accessing Recovery Shell, authenticating with OpenPGP smartcard signature test:

Screenshot_20260714_144547

Booting from USB

Screenshot_20260714_144655 Screenshot_20260714_144710

Note that OEM factory reset/Re-Ownership, flashing, changing config is not guarded since Heads makes tampering evident and doesn't pretent preventing it.

User has to create key material backup from OEM factory reset/ Re-Ownership

Screenshot_20260714_141627

Answering yes to
Screenshot_20260714_141815

The for sake of this test, as per doc/qemu.md guidelines, on host (Qemu still can't inject stuff in firmware):

We want to locally map virtualized thumb drive to host:

sudo losetup --find --show --partscan ./build/x86/qemu-coreboot-fbwhiptail-tpm2-prod_quiet/usb_fd.raw 
/dev/loop36

We want to extract public key from public partition created on virtualized thumb drive:

sudo mount /dev/loop36p2 /media/cdrom/
cp /media/cdrom/pubkey.asc pubkey.asc 
sudo umount /media/cdrom

And for sake of dealing with qemu limitations, inject public key:
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2-prod_quiet PUBKEY_ASC=pubkey.asc inject_gpg run

Copilot AI review requested due to automatic review settings July 14, 2026 18:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR extends Heads’ GPG provisioning/recovery capabilities by adding a “reprovision smartcard from GPG key backup” flow, factoring common GPG/smartcard operations into shared initrd functions, wiring the new flow into UI entry points, and documenting the recovery/testing workflows.

Changes:

  • Added shared gpg_* helpers in initrd/etc/gpg_functions.sh, including a new reprovision_smartcard_from_backup() end-to-end recovery flow.
  • Refactored oem-factory-reset.sh to delegate to the new shared helpers and added UI menu options to trigger reprovisioning.
  • Updated documentation for recovery-shell authentication semantics and QEMU testing workflows.

Reviewed changes

Copilot reviewed 6 out of 9 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
initrd/etc/gpg_functions.sh Adds shared smartcard/GPG helper functions and implements the reprovision-from-backup flow.
initrd/bin/oem-factory-reset.sh Replaces inlined GPG/smartcard logic with thin wrappers calling shared gpg_* functions.
initrd/bin/gui-init.sh Adds new reprovision menu options to “missing key” flows and clean-boot wizard.
initrd/bin/gpg-gui.sh Adds k option to trigger reprovisioning from the GPG Management Menu.
doc/recovery-shell.md Documents recovery-shell authentication and configuration-reset implications.
doc/qemu.md Documents QEMU USB workflow improvements and reprovision-from-backup testing steps.
doc/gpg.md Adds a “Restoring Keys from Backup” section.
doc/configuring-keys.md Documents the restore-from-backup recovery procedure.
doc/architecture.md Updates architecture text to reference reprovision path and recovery-shell auth docs.

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

Comment thread initrd/etc/gpg_functions.sh
Comment thread initrd/etc/gpg_functions.sh
Comment thread initrd/etc/gpg_functions.sh
Comment thread initrd/etc/gpg_functions.sh Outdated
Comment thread initrd/etc/gpg_functions.sh
Comment thread initrd/etc/gpg_functions.sh Outdated
Comment thread initrd/etc/gpg_functions.sh Outdated
Comment thread initrd/etc/gpg_functions.sh Outdated
Comment thread initrd/etc/gpg_functions.sh Outdated
Comment thread initrd/etc/gpg_functions.sh
@tlaurion
tlaurion marked this pull request as draft July 14, 2026 19:00
@tlaurion
tlaurion force-pushed the reprovision-smartcard-from-backup branch from 3a7203e to 1fe0412 Compare July 14, 2026 19:42
@tlaurion
tlaurion requested a review from Copilot July 14, 2026 19:42

Copilot AI left a comment

Copy link
Copy Markdown

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 6 out of 9 changed files in this pull request and generated 5 comments.

Comment thread initrd/etc/gpg_functions.sh Outdated
Comment thread initrd/etc/gpg_functions.sh
Comment thread initrd/etc/gpg_functions.sh Outdated
Comment thread initrd/etc/gpg_functions.sh Outdated
Comment thread initrd/etc/gpg_functions.sh Outdated
tlaurion added a commit to tlaurion/heads that referenced this pull request Jul 14, 2026
- Remove incorrect || [ $? -eq 2 ] pattern: exit code 2 from
  gpg --import is a fatal error, not "unchanged" as previously documented
- Fix pubkey.asc import: check success/failure properly, fall back to
  keyring export on failure instead of silently continuing with stale PUBKEY
- Fix gpg_reset_nk3_secret_app: add local error_code to prevent global
  scope leak, implicit return 0 for non-NK3 devices (non-zero fall-through
  broke OEM reset on NK3-incompatible hardware)
- Fix partition derivation for NVMe/MMC: sed pattern (p?)[0-9]+$ was
  removing the p separator from nvme0n1p1 -> nvme0n1, producing
  nvme0n12 instead of nvme0n1p2. Use [0-9]+$ without p? capture.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion
tlaurion force-pushed the reprovision-smartcard-from-backup branch from 1fe0412 to 3d9fcc5 Compare July 14, 2026 20:16
@tlaurion
tlaurion requested a review from Copilot July 14, 2026 20:17

Copilot AI left a comment

Copy link
Copy Markdown

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 6 out of 9 changed files in this pull request and generated 5 comments.

Comment thread initrd/etc/gpg_functions.sh
Comment thread initrd/etc/gpg_functions.sh Outdated
Comment thread initrd/etc/gpg_functions.sh
Comment thread initrd/etc/gpg_functions.sh
Comment thread initrd/etc/gpg_functions.sh Outdated
@tlaurion
tlaurion requested a review from Copilot July 14, 2026 20:26
tlaurion added a commit to tlaurion/heads that referenced this pull request Jul 14, 2026
- Remove incorrect || [ $? -eq 2 ] pattern: exit code 2 from
  gpg --import is a fatal error, not "unchanged" as previously documented
- Fix pubkey.asc import: check success/failure properly, fall back to
  keyring export on failure instead of silently continuing with stale PUBKEY
- Fix gpg_reset_nk3_secret_app: add local error_code to prevent global
  scope leak, implicit return 0 for non-NK3 devices (non-zero fall-through
  broke OEM reset on NK3-incompatible hardware)
- Fix partition derivation for NVMe/MMC: sed pattern (p?)[0-9]+$ was
  removing the p separator from nvme0n1p1 -> nvme0n1, producing
  nvme0n12 instead of nvme0n1p2. Use [0-9]+$ without p? capture.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion
tlaurion force-pushed the reprovision-smartcard-from-backup branch from 6cb756b to 2e873e9 Compare July 14, 2026 20:28

Copilot AI left a comment

Copy link
Copy Markdown

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 6 out of 9 changed files in this pull request and generated 6 comments.

Comment thread initrd/etc/gpg_functions.sh Outdated
Comment thread initrd/etc/gpg_functions.sh
Comment thread initrd/etc/gpg_functions.sh
Comment thread initrd/etc/gpg_functions.sh
Comment thread initrd/etc/gpg_functions.sh
Comment thread doc/recovery-shell.md Outdated
tlaurion added a commit to tlaurion/heads that referenced this pull request Jul 14, 2026
- Add local rc declarations in gpg_card_factory_reset,
  gpg_card_change_pin, and gpg_keytocard_subkeys to prevent
  global scope leaks
- Add _luks_cleanup helper to close LUKS mappings on all error
  paths (removed broken EXIT trap that does not fire on function
  return)
- Re-run NK3 Secrets app reset with custom PIN when factory
  reset is retried from default to custom PIN
- Add chmod 600 on /tmp/secret/gpg_pin to match existing
  cache_gpg_signing_pin convention
- Fix recovery-shell.md auth scope: USB/external media boot
  is also gated by gpg_auth via media-scan.sh

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
tlaurion added a commit to tlaurion/heads that referenced this pull request Jul 14, 2026
- Add local rc declarations in gpg_card_factory_reset,
  gpg_card_change_pin, and gpg_keytocard_subkeys to prevent
  global scope leaks
- Add _luks_cleanup helper to close LUKS mappings on all error
  paths (removed broken EXIT trap that does not fire on function
  return)
- Re-run NK3 Secrets app reset with custom PIN when factory
  reset is retried from default to custom PIN
- Add chmod 600 on /tmp/secret/gpg_pin to match existing
  cache_gpg_signing_pin convention
- Fix recovery-shell.md auth scope: USB/external media boot
  is also gated by gpg_auth via media-scan.sh

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion
tlaurion force-pushed the reprovision-smartcard-from-backup branch from b71e03e to 6da58d4 Compare July 14, 2026 21:01
@tlaurion
tlaurion requested a review from Copilot July 14, 2026 21:04

Copilot AI left a comment

Copy link
Copy Markdown

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 6 out of 9 changed files in this pull request and generated 2 comments.

Comment thread initrd/etc/gpg_functions.sh
Comment thread doc/qemu.md Outdated
tlaurion added a commit to tlaurion/heads that referenced this pull request Jul 14, 2026
- Fix 6 instances of $? clobbered by intervening TRACE_FUNC/DEBUG
  calls: capture rc=$? immediately after each DO_WITH_DEBUG gpg
  pipeline, check $rc (adds local rc declarations).
- Replace --passphrase-file with --passphrase-fd 3 3< <(...) to
  avoid leaking the PIN value through /proc/<pid>/cmdline of the
  child echo process (3 sites: factory reset, card identity, import).
- Fix algo_code/bit_len extraction: add head -1 to prevent multi-line
  values when multiple keys are present in the backup.
- Fix STATUS_OK on public partition mount: only emit on success.
- Fix gpg_reset_nk3_secret_app: return actual hotp_verification
  error code, add local error_code, explicit return 0 for non-NK3.
- Remove incorrect || [ $? -eq 2 ] pattern: gpg --import exit code 2
  is a fatal error, not "unchanged".
- Fix pubkey.asc import: check success properly, fall back to keyring
  export on failure.
- Fix partition derivation for NVMe/MMC: use [0-9]+$ without (p?)
  capture that was removing the p separator.
- Add _luks_cleanup helper called on every error return path to
  close LUKS mappings (removed broken EXIT trap).
- Re-run NK3 Secrets app reset with custom PIN when factory reset
  is retried from default to custom PIN.
- Add chmod 600 on /tmp/secret/gpg_pin to match existing convention.
- Fix recovery-shell.md: gpg_auth also guards USB/external boot entry
  via media-scan.sh.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion
tlaurion force-pushed the reprovision-smartcard-from-backup branch from 6da58d4 to ff388b5 Compare July 14, 2026 21:11
tlaurion added a commit to tlaurion/heads that referenced this pull request Jul 14, 2026
- Fix 6 instances of $? clobbered by intervening TRACE_FUNC/DEBUG
  calls: capture rc=$? immediately after each DO_WITH_DEBUG gpg
  pipeline, check $rc (adds local rc declarations).
- Replace --passphrase-file with --passphrase-fd 3 3< <(...) to
  avoid leaking the PIN value through /proc/<pid>/cmdline of the
  child echo process (3 sites: factory reset, card identity, import).
- Fix algo_code/bit_len extraction: add head -1 to prevent multi-line
  values when multiple keys are present in the backup.
- Fix STATUS_OK on public partition mount: only emit on success.
- Fix gpg_reset_nk3_secret_app: return actual hotp_verification
  error code, add local error_code, explicit return 0 for non-NK3.
- Remove incorrect || [ $? -eq 2 ] pattern: gpg --import exit code 2
  is a fatal error, not "unchanged".
- Fix pubkey.asc import: check success properly, fall back to keyring
  export on failure.
- Fix partition derivation for NVMe/MMC: use [0-9]+$ without (p?)
  capture that was removing the p separator.
- Add _luks_cleanup helper called on every error return path to
  close LUKS mappings (removed broken EXIT trap).
- Re-run NK3 Secrets app reset with custom PIN when factory reset
  is retried from default to custom PIN.
- Add chmod 600 on /tmp/secret/gpg_pin to match existing convention.
- Fix recovery-shell.md: gpg_auth also guards USB/external boot entry
  via media-scan.sh.
- Write backup passphrase to /tmp/secret/backup_pass, call mount-usb.sh
  with --pass-file instead of --pass to avoid argv leak.
- Add --pass-file option to mount-usb.sh (reads passphrase from file).
- Fix doc/qemu.md: clarify ./qemu_img/ vs ~/Qemu_img/ roles.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
@tlaurion
tlaurion force-pushed the reprovision-smartcard-from-backup branch from ff388b5 to 92a5ba6 Compare July 14, 2026 21:23
@tlaurion
tlaurion requested a review from Copilot July 14, 2026 21:25

Copilot AI left a comment

Copy link
Copy Markdown

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 6 out of 10 changed files in this pull request and generated 1 comment.

Comment thread initrd/etc/gpg_functions.sh Outdated
@tlaurion
tlaurion force-pushed the reprovision-smartcard-from-backup branch from 6e550da to 4ab154a Compare July 15, 2026 01:04
@tlaurion
tlaurion requested a review from Copilot July 15, 2026 01:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@tlaurion
tlaurion force-pushed the reprovision-smartcard-from-backup branch 14 times, most recently from 3396cfd to 1e59d36 Compare July 16, 2026 22:07
…use, add reprovision flow

Extract shared OpenPGP smartcard management functions from
initrd/bin/oem-factory-reset.sh into initrd/etc/gpg_functions.sh
so they can be reused by multiple callers.  OEM functions become
thin wrappers passing global variables as positional args; the
reprovision flow calls the same shared functions to restore GPG
subkeys from a LUKS-encrypted backup USB onto a replacement USB
Security dongle.

Shared functions (replacing OEM inline code):
- gpg_card_factory_reset(): factory-reset + forcesig + key-attr
  (RSA and ECC/P-256), parameterized on admin PIN, with --expert
  on RSA key-attr for key sizes above 2048 bit
- gpg_keytocard_subkeys(): enable USB, verify card, move subkeys
  to slots 1-3 (sign, encrypt, auth)
- gpg_set_card_identity(): cardholder name and login fields
- gpg_reset_nk3_secret_app(): Nitrokey 3 Secrets app reset
- gpg_card_change_pin(): GPG User/Admin PIN change
- _luks_cleanup(): unmount /media and close LUKS mappings

New reprovision flow (reprovision_smartcard_from_backup()):
10-phase flow: mount LUKS backup -> detect key type -> factory-
reset card -> import subkeys -> set identity -> sign /boot -> flash

GUI integration:
- k option in GPG Management Menu (gpg-gui.sh), always visible
- K option in prompt_missing_gpg_key_action (gui-init.sh)
- Clean boot wizard: OEM reset, reprovision, or ignore

Code quality fixes:
- Add --pass-file option to mount-usb.sh (reads file into $PASS)
- Reset card_admin_pin to default 12345678 after factory-reset
- Wait for gpg card after USB storage init (release_scdaemon)
- Validate backup passphrase is non-empty before proceeding
- Use glob-based param_files ordering matching check_config
  (fixes BAD signature regression where manual ordering differed)
- Track tpm_counter_ok flag and warn if TPM counter not created

Documentation:
- doc/recovery-shell.md: Authentication section (gpg_auth scope,
  what it prevents and does not prevent, SPI flash dump threat,
  USB boot guard), Resetting Configuration section
- doc/configuring-keys.md: Restoring Keys from Backup section
- doc/gpg.md: Restoring Keys from Backup section (cross-ref)
- doc/architecture.md: reprovision option in CONFIG_HAVE description
- doc/qemu.md: Resetting state section for QEMU testing

Tested on QEMU with canokey-qemu (virtual Canokey): OEM factory
reset creates LUKS backup, reprovision restores subkeys to
replacement dongle, /boot signed and verified, gpg_auth works
after reboot.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
- Fix real.gitclean to use git clean -ffxd so nested git repos are deleted rather than skipped
- Remove overwrite_canary_if_coreboot_git from nuclear targets since repos are wiped
- Rename real.gitclean_keep_packages to real.gitclean_keep_pkg
- Rename real.gitclean_keep_packages_and_build to real.gitclean_keep_build
- Add real.devclean, real.devclean_pkg, real.devclean_build using git clean -fxd that skip nested repos and recreate the canary
- Update doc/modules.md reference table

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
The empty-keyring error dialog in check_gpg_key only offered adding a GPG
key, OEM Factory Reset, ignoring the error, or exiting to the recovery
shell. Reprovisioning the USB security dongle from the GPG key backup was
reachable only one level deeper, via the GPG management menu.

- Add 'K' (Reprovision USB Security dongle from GPG key backup) entry to
  the empty-keyring error menu, mirroring prompt_missing_gpg_key_action.
- Route 'K' to reprovision_smartcard_from_backup and clear the error
  background color on success, matching the 'g' arm.
- Bump the menu list height from 4 to 5 for the additional entry.

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

The confirmation prompt advertises [Y/d/b], but the selection loop in
user_select only matched lowercase 'y' and 'd'. Pressing 'Y' re-prompted
the menu instead of booting; Enter worked only because an empty read
defaults to 'y'.

- Normalize option_confirm to lowercase after reading in
  confirm_menu_option, so 'Y' and 'D' behave like 'y' and 'd'.
- Matches the case handling already used for default_confirm in
  save_default_option.

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

The Measured Integrity Report only offered OEM Factory Reset and Continue
when /boot was intact but the signing key was missing or not ROM-trusted.
Users holding a GPG key backup could not reach reprovision_smartcard_from_backup
from the report; they had to exit to the GPG management menu.

- Add 'K' (Reprovision USB Security dongle from GPG key backup) to the
  /boot-intact-but-no-private-key menu, routed to
  reprovision_smartcard_from_backup.
- Add 'K' to the DONGLE KEY NOT ROM-TRUSTED menu (i/r/o/c -> i/r/o/K/c),
  so a wiped or re-keyed dongle can be restored to the ROM-trusted
  identity from backup instead of forcing re-ownership.
- Bump both menu list heights for the additional entry.

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

Two recovery paths still funneled users holding a GPG key backup straight
into OEM Factory Reset / Re-Ownership without offering reprovision from
backup:

- The TPM State Inconsistent (rollback preflight) dialog only offered
  integrity report, OEM Factory Reset, TPM reset, and main menu.
- clean_boot_check launched oem-factory-reset.sh directly via a yes/no
  prompt when no kexec files and no GPG keys were found.

- Add 'K' (Reprovision USB Security dongle from GPG key backup) to the
  rollback preflight menu (i/o/t/m -> i/o/K/t/m), routed to
  reprovision_smartcard_from_backup; the loop re-displays since the TPM
  counter issue is unaffected by key provisioning.
- Convert the clean-boot yes/no prompt into a menu offering OEM Factory
  Reset, reprovision from backup, ignore and continue, and recovery shell.
- Bump the preflight menu list height from 4 to 5 for the extra entry.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
… reprovision when TPM reset is required

When reprovision_smartcard_from_backup runs after the rollback preflight
failed (tpm_reset_required set), Phase 8 still attempted tpmr.sh
counter_create.  tpm2 nvdefine -C o requires the TPM owner passphrase,
which is unknown in that state (TPM was reset or swapped), so the user
was prompted 3 times for a passphrase that cannot work, each failing
with authorization error 0x9a2.

Guard counter creation with ! tpm_reset_required so the flow proceeds
straight to the existing reset-TPM guidance.  Mirrors the guards already
used by generate_totp_hotp and prompt_update_checksums.

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
…eport when marker set

When the rollback counter preflight fails, set_tpm_reset_required marks
the TPM state inconsistent.  The integrity report still said "Reseal
required" and told the user to generate a new HOTP/TOTP secret, but
generate_totp_hotp refuses to run while the marker is set, so the
guidance pointed at a blocked action.

- Branch the TOTP state display on tpm_reset_required: report "TPM reset
  required (rollback counter cannot be verified)" instead of "Reseal
  required" when the marker is present.
- Replace the "generate a new HOTP/TOTP secret" note with reset-the-TPM
  guidance when tpm_reset_required, since reset_tpm re-creates the
  rollback counter and regenerates TOTP/HOTP in one flow.

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

Copilot AI left a comment

Copy link
Copy Markdown

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 13 changed files in this pull request and generated no new comments.

Suppressed comments (3)

initrd/etc/gpg_functions.sh:518

  • UID parsing sets key_name to the full UID string (often including the <email> portion). That ends up writing an email address into the cardholder name fields in gpg_set_card_identity. Strip comment and <...> from the UID when deriving key_name.
	if echo "$uid_line" | grep -q '('; then
		key_name="$(echo "$uid_line" | sed 's/ (.*//')"
		key_comment="$(echo "$uid_line" | sed 's/.*(//;s/).*//')"
	else
		key_name="$uid_line"

initrd/etc/gpg_functions.sh:308

  • gpg_set_card_identity accepts card_admin_pin but never uses it. That makes the function depend on scdaemon PIN caching from a previous operation and contradicts the comment/PR description about explicit admin PIN support. Pass the PIN via --passphrase-fd (same approach used in gpg_card_factory_reset) so this works reliably even if scdaemon was restarted.
		fi
		echo "quit"
	} | DO_WITH_DEBUG gpg --command-fd=0 --status-fd=2 --pinentry-mode=loopback --card-edit \
		>/tmp/gpg_card_edit_output 2>&1 ||
		DIE "Failed to set identity fields on OpenPGP smartcard"

initrd/etc/gpg_functions.sh:724

  • The TPM rollback counter warning is unconditional when tpm_counter_ok is unset, so it will also display on systems with no TPM or with rollback checks disabled. Gate this warning on CONFIG_TPM=y (and rollback checks enabled) so users don't get incorrect instructions.
	if [ "$tpm_counter_ok" != "y" ]; then
		WARN "TPM rollback counter was not created. Reset the TPM from"
		WARN "Options -> TPM/TOTP/HOTP Options -> Reset the TPM before"
		WARN "the next boot to avoid being dropped into recovery shell."
	fi

…set guidance

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants