diff --git a/initrd/bin/gui-init.sh b/initrd/bin/gui-init.sh index 710b9d810..7c7164e7b 100755 --- a/initrd/bin/gui-init.sh +++ b/initrd/bin/gui-init.sh @@ -249,17 +249,17 @@ gate_reseal_with_integrity_report() { # starting the NK3 CCID teardown. This safety call covers the # case where scdaemon was restarted between then and now. release_scdaemon - STATUS "Checking USB security dongle presence before sealing" + STATUS "Checking $DONGLE_BRAND presence before sealing" DEBUG "gate_reseal_with_integrity_report: checking HOTP token presence" if hotp_verification info >/dev/null 2>&1; then token_ok="y" - STATUS_OK "USB security dongle present and accessible" + STATUS_OK "$DONGLE_BRAND present and accessible" break fi DEBUG "gate_reseal_with_integrity_report: HOTP token not accessible" - if ! whiptail_warning --title "USB Security Dongle Required" \ + if ! whiptail_warning --title "$DONGLE_BRAND Required" \ --yes-button "Retry" --no-button "Abort" \ - --yesno "Your USB security dongle must be present before sealing new secrets.\n\nInsert the dongle and choose Retry, or Abort." 0 80; then + --yesno "Your $DONGLE_BRAND must be present before sealing new secrets.\n\nInsert the dongle and choose Retry, or Abort." 0 80; then return 1 fi done @@ -292,7 +292,7 @@ generate_totp_hotp() { if [ -x /bin/hotp_verification ]; then # If we have a TPM and a HOTP USB Security dongle if [ "$CONFIG_TOTP_SKIP_QRCODE" != y ]; then - INPUT "Once you have scanned the QR code, press Enter to configure your HOTP USB Security dongle (e.g. Librem Key or Nitrokey)" + INPUT "Once you have scanned the QR code, press Enter to configure your $DONGLE_BRAND" fi TRACE_FUNC /bin/seal-hotpkey.sh || DIE "Failed to generate HOTP secret" @@ -314,11 +314,11 @@ prompt_missing_gpg_key_action() { TRACE_FUNC local retry_label retry_msg if [ "$CONFIG_HAVE_GPG_KEY_BACKUP" = "y" ]; then - retry_label=' Retry (insert signing card or backup USB drive)' - retry_msg="Cannot sign /boot because no private GPG signing key is available (card not inserted, wiped, or key not set up).\n\nInsert your signing card or backup USB drive and retry.\n\nHow would you like to proceed?" + retry_label=" Retry (insert $DONGLE_BRAND or backup USB drive)" + retry_msg="Cannot sign /boot because no private GPG signing key is available ($DONGLE_BRAND not inserted, wiped, or key not set up).\n\nInsert your $DONGLE_BRAND or backup USB drive and retry.\n\nHow would you like to proceed?" else - retry_label=' Retry (after connecting the correct signing card)' - retry_msg="Cannot sign /boot because no private GPG signing key is available (card not inserted, wiped, or key not set up).\n\nIf you have the correct signing card, insert it and retry.\n\nHow would you like to proceed?" + retry_label=" Retry (after connecting $DONGLE_BRAND)" + retry_msg="Cannot sign /boot because no private GPG signing key is available ($DONGLE_BRAND not inserted, wiped, or key not set up).\n\nInsert your $DONGLE_BRAND and retry.\n\nHow would you like to proceed?" fi whiptail_error --title "ERROR: GPG signing key unavailable" \ --menu "$retry_msg" 0 80 4 \ diff --git a/initrd/bin/oem-factory-reset.sh b/initrd/bin/oem-factory-reset.sh index 2755cbb0b..32539f1da 100755 --- a/initrd/bin/oem-factory-reset.sh +++ b/initrd/bin/oem-factory-reset.sh @@ -23,6 +23,10 @@ rm -f /tmp/hotpkey_fw_shown TRACE_FUNC +# Enable USB and detect branding early — $DONGLE_BRAND is used throughout this script. +enable_usb +detect_usb_security_dongle_branding + # use TERM to exit on error trap "exit 1" TERM export TOP_PID=$$ @@ -180,7 +184,7 @@ reset_nk3_secret_app() { else error_code=$? if [ $error_code -eq 3 ] && [ $attempt -lt 3 ]; then - whiptail_warning --msgbox "Nitrokey 3 requires physical presence: touch the dongle when requested" $HEIGHT $WIDTH --title "Nk3 secrets app reset attempt: $attempt/3" + whiptail_warning --msgbox "$DONGLE_BRAND requires physical presence: touch the dongle when requested" $HEIGHT $WIDTH --title "$DONGLE_BRAND secrets app reset attempt: $attempt/3" else whiptail_error_die "Nitrokey 3's Secrets app reset failed with error:$error_code. Contact Nitrokey support" fi @@ -1043,7 +1047,7 @@ usb_security_token_capabilities_check() { DONGLE_FW_VERSION="$(echo "$hotp_token_info" | grep "Firmware:" | sed 's/.*: *//')" case "$DONGLE_FW_VERSION" in v*) ;; *) DONGLE_FW_VERSION="v$DONGLE_FW_VERSION" ;; esac fi - DEBUG "Dongle firmware version: $DONGLE_FW_VERSION" + DEBUG "$DONGLE_BRAND firmware version: $DONGLE_FW_VERSION" fi fi } @@ -1222,7 +1226,7 @@ if [ "$use_defaults" == "n" -o "$use_defaults" == "N" ]; then INPUT "Enter desired NK3 Secrets app PIN / GPG Admin PIN (6-${MAX_HOTP_GPG_PIN_LENGTH} chars):" -r ADMIN_PIN done else - NOTE "GPG Admin PIN: management tasks on USB Security dongle, seal measurements under HOTP. 3 attempts max, locks Admin out. DO NOT FORGET. Recommended: 2 words" + NOTE "GPG Admin PIN: management tasks on $DONGLE_BRAND, seal measurements under HOTP. 3 attempts max, locks Admin out. DO NOT FORGET. Recommended: 2 words" while [[ ${#ADMIN_PIN} -lt 6 ]] || [[ ${#ADMIN_PIN} -gt $MAX_HOTP_GPG_PIN_LENGTH ]]; do INPUT "Enter desired GPG Admin PIN (6-${MAX_HOTP_GPG_PIN_LENGTH} chars):" -r ADMIN_PIN done @@ -1320,10 +1324,10 @@ fi if [ "$GPG_GEN_KEY_IN_MEMORY" = "n" -o "$GPG_GEN_KEY_IN_MEMORY_COPY_TO_SMARTCARD" = "y" ]; then enable_usb if ! gpg --card-status >/dev/null 2>&1; then - local_whiptail_error "Can't access USB Security dongle; \nPlease remove and reinsert, then press Enter." + local_whiptail_error "Can't access $DONGLE_BRAND; \nPlease remove and reinsert, then press Enter." if ! gpg --card-status >/dev/null 2>/tmp/error; then ERROR=$(tail -n 1 /tmp/error | fold -s) - whiptail_error_die "Unable to detect USB Security dongle:\n\n${ERROR}" + whiptail_error_die "Unable to detect $DONGLE_BRAND:\n\n${ERROR}" fi fi @@ -1605,7 +1609,7 @@ if [ "$CONFIG_TPM" = "y" ]; then passphrases+="TPM Owner Passphrase: ${TPM_PASS}\n" fi -#if nk3 detected, we add the NK3 Secrets App PIN +#if nk3 detected, we add the NK3 Secrets app PIN if [ "$DONGLE_BRAND" = "Nitrokey 3" ]; then passphrases+="Nitrokey 3 Secrets app PIN: ${ADMIN_PIN}\n" fi diff --git a/initrd/bin/seal-hotpkey.sh b/initrd/bin/seal-hotpkey.sh index 54aa76c8b..b73ed9dee 100755 --- a/initrd/bin/seal-hotpkey.sh +++ b/initrd/bin/seal-hotpkey.sh @@ -88,7 +88,8 @@ DEBUG "Signature key was created at $(date -d "@$gpg_key_create_time")" now_date="$(date '+%s')" # Get the number of HOTP related PIN retry attempts remaining. -# NK3 uses "Secrets app PIN counter"; all pre-NK3 devices use "Card counters: Admin". +# NK3 uses "Secrets app PIN counter" (factory default: 8 attempts); +# all pre-NK3 devices use "Card counters: Admin" (factory default: 3 attempts). if [ "$DONGLE_BRAND" = "Nitrokey 3" ]; then admin_pin_retries=$(echo "$hotp_token_info" | grep "Secrets app PIN counter:" | cut -d ':' -f 2 | tr -d ' ') prompt_message="Secrets app" @@ -103,6 +104,8 @@ DEBUG "HOTP related PIN retry counter is $admin_pin_retries" hotpkey_fw_display "$hotp_token_info" "$DONGLE_BRAND" # Re-query and display the current PIN retry counter before each manual prompt. +# Updates the global $admin_pin_retries (no local keyword) so callers can use +# the fresh value for decisions (e.g. max_attempts calculation below). # prompt_message is already set for the device type (NK3 vs older), reuse it. show_pin_retries() { local info @@ -113,7 +116,7 @@ show_pin_retries() { admin_pin_retries=$(echo "$info" | grep "Card counters: Admin" | grep -o 'Admin [0-9]*' | grep -o '[0-9]*') fi admin_pin_retries="${admin_pin_retries:-0}" - STATUS "$DONGLE_BRAND GPG Admin PIN retries remaining: $(pin_color "$admin_pin_retries")${admin_pin_retries}\033[0m" + STATUS "$DONGLE_BRAND ${prompt_message} PIN retries remaining: $(pin_color "$admin_pin_retries")${admin_pin_retries}\033[0m" } # Try using factory default admin PIN for 1 month following OEM reset to ease @@ -131,7 +134,7 @@ if [ "$((now_date - gpg_key_create_time))" -gt "$month_secs" ]; then elif [ "$admin_pin_retries" -lt 3 ]; then DEBUG "Not trying default PIN ($admin_pin): only $admin_pin_retries attempt(s) left" else - STATUS "Trying GPG Admin PIN to seal HOTP secret on $DONGLE_BRAND" + STATUS "Trying ${prompt_message} PIN to seal HOTP secret on $DONGLE_BRAND" # NK3 requires physical touch confirmation for the initialize operation if [ "$DONGLE_BRAND" = "Nitrokey 3" ]; then NOTE "Nitrokey 3 requires physical presence: touch the dongle when prompted" @@ -144,30 +147,71 @@ fi if [ "$admin_pin_status" -ne 0 ]; then + # If the default PIN was tried and failed, we consumed 1 attempt. + # Re-read the counter and limit user attempts accordingly. + # Leave at least 1 attempt unconsumed to avoid accidental lockout. + # + # max_attempts calculation: + # - Read current retry counter (may be lower if default PIN consumed 1) + # - Subtract 1 to preserve one final attempt for the user + # - Cap at 3 to match the pre-NK3 factory default, so the user experience + # is consistent regardless of device. + # - If the counter read is unreliable (0 or 1), fall back to 3 attempts + # so the user is never blocked from sealing. + # + # Example outcomes for NK3 (factory default: 8): + # Default PIN skipped (key >1 month old) -> max_attempts = min(8-1, 3) = 3 + # Default PIN tried & failed (8 -> 7 remaining) -> max_attempts = min(7-1, 3) = 3 + # Default PIN tried & failed (4 -> 3 remaining) -> max_attempts = min(3-1, 3) = 2 + # Default PIN tried & failed (2 -> 1 remaining) -> max_attempts = 3 (fallback, don't block) + # Counter read failed (0 or empty) -> max_attempts = 3 (fallback, don't block) + # + # Example outcomes for pre-NK3 (factory default: 3): + # Default PIN skipped (key >1 month old) -> max_attempts = min(3-1, 3) = 2 + # Default PIN tried & failed (3 -> 2 remaining) -> max_attempts = min(2-1, 3) = 1 + # Counter read failed (0 or empty) -> max_attempts = 3 (fallback, don't block) + # Re-read counter without displaying (loop will show it) + info="$(hotp_verification info 2>/dev/null)" || true + if [ "$DONGLE_BRAND" = "Nitrokey 3" ]; then + admin_pin_retries=$(echo "$info" | grep "Secrets app PIN counter:" | cut -d ':' -f 2 | tr -d ' ') + else + admin_pin_retries=$(echo "$info" | grep "Card counters: Admin" | grep -o 'Admin [0-9]*' | grep -o '[0-9]*') + fi + admin_pin_retries="${admin_pin_retries:-0}" + if [ "$admin_pin_retries" -ge 2 ]; then + max_attempts=$((admin_pin_retries - 1)) + [ "$max_attempts" -gt 3 ] && max_attempts=3 + else + max_attempts=3 + fi + # prompt user for PIN; re-query counter before each attempt so the user # sees the decremented count after a wrong PIN (same pattern as kexec-sign-config.sh) - for tries in 1 2 3; do + for tries in $(seq 1 $max_attempts); do show_pin_retries if [ "$tries" -eq 1 ]; then - INPUT "Enter your $DONGLE_BRAND GPG Admin PIN (attempt $tries/3):" -r -s admin_pin + INPUT "Enter your $DONGLE_BRAND ${prompt_message} PIN (attempt $tries/$max_attempts):" -r -s admin_pin else - INPUT "Wrong PIN - re-enter your $DONGLE_BRAND GPG Admin PIN (attempt $tries/3):" -r -s admin_pin + INPUT "Wrong PIN - re-enter your $DONGLE_BRAND ${prompt_message} PIN (attempt $tries/$max_attempts):" -r -s admin_pin fi if hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$DONGLE_BRAND"; then break fi - if [ "$tries" -eq 3 ]; then + if [ "$tries" -eq "$max_attempts" ]; then # don't leak key on failure shred -n 10 -z -u "$HOTP_SECRET" 2>/dev/null case "$DONGLE_BRAND" in - "Nitrokey Pro" | "Nitrokey Storage" | "Nitrokey 3") - DIE "Setting HOTP secret on $DONGLE_BRAND failed after 3 attempts. To reset GPG Admin PIN: redo Re-Ownership, or use Nitrokey App 2, or contact Nitrokey support." + "Nitrokey 3") + DIE "Setting HOTP secret on $DONGLE_BRAND failed after $max_attempts attempts. To reset ${prompt_message} PIN: redo Re-Ownership, or use Nitrokey App 2, or contact Nitrokey support." + ;; + "Nitrokey Pro" | "Nitrokey Storage") + DIE "Setting HOTP secret on $DONGLE_BRAND failed after $max_attempts attempts. To reset GPG Admin PIN: redo Re-Ownership, or use Nitrokey App 2, or contact Nitrokey support." ;; "Librem Key") - DIE "Setting HOTP secret on $DONGLE_BRAND failed after 3 attempts. To reset GPG Admin PIN: redo Re-Ownership or contact Purism support." + DIE "Setting HOTP secret on $DONGLE_BRAND failed after $max_attempts attempts. To reset GPG Admin PIN: redo Re-Ownership or contact Purism support." ;; *) - DIE "Setting HOTP secret failed after 3 attempts" + DIE "Setting HOTP secret failed after $max_attempts attempts" ;; esac fi @@ -175,7 +219,7 @@ if [ "$admin_pin_status" -ne 0 ]; then else # Default PIN was accepted — security reminder, not a fatal error. # NOTE prints blank lines before/after and is always visible; no INPUT needed. - NOTE "Default GPG Admin PIN detected. Change it via Options --> OEM Factory Reset / Re-Ownership." + NOTE "Default ${prompt_message} PIN detected. Change it via Options --> OEM Factory Reset / Re-Ownership." fi # HOTP key no longer needed diff --git a/initrd/etc/functions.sh b/initrd/etc/functions.sh index b3c9ff333..20802909f 100644 --- a/initrd/etc/functions.sh +++ b/initrd/etc/functions.sh @@ -500,6 +500,22 @@ pin_color() { # 1050:0404 Yubikey 5 (FIDO+CCID) detect_usb_security_dongle_branding() { TRACE_FUNC + local usb_was_enabled="${_USB_ENABLED:-n}" + # Fast path: avoid USB re-init and lsusb scan when branding is already known + # and USB has already been initialized in this process. + if [ "$DONGLE_BRAND" != "USB Security dongle" ] \ + && [ -n "$DONGLE_BRAND" ] \ + && [ "$usb_was_enabled" = "y" ]; then + return + fi + + # 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 + + # If branding is already specific, USB is now ready and no re-scan is needed. + [ "$DONGLE_BRAND" != "USB Security dongle" ] && [ -n "$DONGLE_BRAND" ] && return local lsusb_out lsusb_out="$(lsusb)" DEBUG "lsusb output: $lsusb_out" @@ -644,7 +660,7 @@ cache_gpg_signing_pin() { # keystrokes from previous prompts cannot silently satisfy this read. local card_confirm="" if [ "$CONFIG_HAVE_GPG_KEY_BACKUP" == "y" ]; then - INPUT "Use your GPG security dongle (Enter/y) or backup thumb drive (b)? [Y/b]:" -n 1 -r card_confirm + INPUT "Use your $DONGLE_BRAND (Enter/y) or backup thumb drive (b)? [Y/b]:" -n 1 -r card_confirm while [ "$card_confirm" != "y" \ -a "$card_confirm" != "Y" \ -a "$card_confirm" != "b" \ @@ -831,6 +847,8 @@ cache_gpg_signing_pin() { } confirm_gpg_card() { + enable_usb + detect_usb_security_dongle_branding cache_gpg_signing_pin "$@" } diff --git a/initrd/etc/gui_functions.sh b/initrd/etc/gui_functions.sh index 6e67058f2..871f006c9 100755 --- a/initrd/etc/gui_functions.sh +++ b/initrd/etc/gui_functions.sh @@ -253,6 +253,10 @@ report_integrity_measurements() { DEBUG "integrity report generated at $date_now" STATUS "Preparing Measured Integrity Report - hashing and verifying /boot" + # Detect branding and initialize USB (detect_usb_security_dongle_branding calls + # enable_usb internally and guards against redundant re-detection). + detect_usb_security_dongle_branding + if [ "$CONFIG_TPM" = "y" ]; then totp_state="UNAVAILABLE" if [ "$CONFIG_TPM2_TOOLS" != "y" ] || [ -f /tmp/secret/primary.handle ]; then @@ -271,21 +275,19 @@ report_integrity_measurements() { fi if [ -x /bin/hotp_verification ]; then - enable_usb - STATUS "Checking USB security dongle presence" - local _dongle_brand _hotp_info - _dongle_brand="$(detect_usb_security_dongle_branding)" + STATUS "Checking $DONGLE_BRAND presence" + local _hotp_info DEBUG "report_integrity_measurements: querying HOTP token info" if _hotp_info="$(hotp_verification info 2>/dev/null)"; then - hotp_state="TOKEN PRESENT" - STATUS_OK "USB security dongle detected" - hotpkey_fw_display "$_hotp_info" "$_dongle_brand" - elif [ "$_dongle_brand" != "USB Security dongle" ]; then - hotp_state="TOKEN INCOMPATIBLE" - DEBUG "report_integrity_measurements: $_dongle_brand detected but HOTP verification failed" + hotp_state="$DONGLE_BRAND PRESENT" + STATUS_OK "$DONGLE_BRAND detected" + hotpkey_fw_display "$_hotp_info" "$DONGLE_BRAND" + elif [ "$DONGLE_BRAND" != "USB Security dongle" ]; then + hotp_state="$DONGLE_BRAND INCOMPATIBLE" + DEBUG "report_integrity_measurements: $DONGLE_BRAND detected but HOTP verification failed" else - hotp_state="TOKEN MISSING" - DEBUG "report_integrity_measurements: hotp_verification info failed, hotp_state=TOKEN MISSING" + hotp_state="$DONGLE_BRAND MISSING" + DEBUG "report_integrity_measurements: hotp_verification info failed, hotp_state=$hotp_state" fi fi @@ -351,7 +353,7 @@ report_integrity_measurements() { # Check signing key: try card immediately (USB already up); only prompt if not accessible. # wait_for_gpg_card sets global gpg_output to the card-status output on success. - STATUS "Verifying OpenPGP signing key on USB security dongle" + STATUS "Verifying signing key on $DONGLE_BRAND" enable_usb gpg_output="" local _card_detected=0 @@ -359,7 +361,7 @@ report_integrity_measurements() { _card_detected=1 else whiptail_type "$BG_COLOR_MAIN_MENU" --title 'Signing Card Check' \ - --msgbox "Please insert your OpenPGP signing card (USB security key), then press OK." 0 80 + --msgbox "Please insert your $DONGLE_BRAND and press OK." 0 80 if wait_for_gpg_card 2>/dev/null; then _card_detected=1 fi @@ -368,14 +370,14 @@ report_integrity_measurements() { # Determine signing key state from card-status output (gpg_output set by wait_for_gpg_card). local _card_sig_fpr _rom_fprs signing_key_guidance if [ "$_card_detected" -eq 0 ]; then - signing_key_state="NO DONGLE DETECTED" - signing_key_guidance="No USB security dongle detected. Insert the correct dongle and retry, or perform OEM Factory Reset / Re-Ownership." + signing_key_state="NO $DONGLE_BRAND DETECTED" + signing_key_guidance="No $DONGLE_BRAND detected. Insert the correct dongle and retry, or perform OEM Factory Reset / Re-Ownership." else _card_sig_fpr=$(echo "$gpg_output" | awk -F: '/Signature key/ {gsub(/[[:space:]]/,"",$2); print $2; exit}') if [ -z "$_card_sig_fpr" ] || [ "$_card_sig_fpr" = "[none]" ]; then signing_key_state="DONGLE NOT PROVISIONED" - signing_key_guidance="USB security dongle is connected but has no signing key (unprovisioned or wiped). Provision the dongle with the signing subkey, or perform OEM Factory Reset / Re-Ownership to start fresh with a new key." + signing_key_guidance="$DONGLE_BRAND is connected but has no signing key (unprovisioned or wiped). Provision the dongle with the signing subkey, or perform OEM Factory Reset / Re-Ownership to start fresh with a new key." else _rom_fprs=$(gpg --with-colons --list-keys 2>/dev/null | awk -F: '/^fpr/ {print $10}') @@ -384,7 +386,7 @@ report_integrity_measurements() { signing_key_guidance="" else signing_key_state="DONGLE KEY NOT ROM-TRUSTED" - signing_key_guidance="USB security dongle has a signing key that does not match this firmware's trusted key. OEM Factory Reset / Re-Ownership is required to establish new trusted ownership." + signing_key_guidance="$DONGLE_BRAND has a signing key that does not match this firmware's trusted key. OEM Factory Reset / Re-Ownership is required to establish new trusted ownership." fi fi fi @@ -404,14 +406,14 @@ report_integrity_measurements() { ;; esac case "$hotp_state" in - "TOKEN MISSING") - hotp_display="TOKEN NOT CONNECTED" + *"MISSING") + hotp_display="$DONGLE_BRAND NOT CONNECTED" ;; - "TOKEN PRESENT") - hotp_display="TOKEN CONNECTED (presence confirmed)" + *"PRESENT") + hotp_display="$DONGLE_BRAND CONNECTED (presence confirmed)" ;; - "TOKEN INCOMPATIBLE") - hotp_display="TOKEN INCOMPATIBLE ($_dongle_brand does not support HOTP)" + *"INCOMPATIBLE") + hotp_display="$DONGLE_BRAND INCOMPATIBLE ($DONGLE_BRAND does not support HOTP)" ;; *) hotp_display="$hotp_state" @@ -424,7 +426,7 @@ report_integrity_measurements() { else action_guidance="$sig_guidance" fi - report_body="Date: $date_now\nTOTP: $totp_display\nHOTP: $hotp_display\n\nBoot signature (/boot/kexec.sig): $signature_state\n$sig_detail\nBoot files: $hash_state\nDongle key: $signing_key_state\n\nAction: $action_guidance" + report_body="Date: $date_now\nTOTP: $totp_display\nHOTP: $hotp_display\n\nBoot signature (/boot/kexec.sig): $signature_state\n$sig_detail\nBoot files: $hash_state\n$DONGLE_BRAND key: $signing_key_state\n\nAction: $action_guidance" if [ "$hash_state" != "OK" ]; then report_body="$report_body\n\nIf /boot integrity is not OK, investigate before sealing new secrets or performing TPM reset or re-ownership." fi @@ -438,7 +440,7 @@ report_integrity_measurements() { fi msg="Measured Integrity Report\n\n$report_body" # menu_msg omits the guidance paragraphs to keep the dialog within terminal height - menu_msg="Measured Integrity Report\n\nDate: $date_now\nTOTP: $totp_display\nHOTP: $hotp_display\n\nBoot signature (/boot/kexec.sig): $signature_state\n$sig_detail\nBoot files: $hash_state\nDongle key: $signing_key_state\n\nChoose an action:" + menu_msg="Measured Integrity Report\n\nDate: $date_now\nTOTP: $totp_display\nHOTP: $hotp_display\n\nBoot signature (/boot/kexec.sig): $signature_state\n$sig_detail\nBoot files: $hash_state\n$DONGLE_BRAND key: $signing_key_state\n\nChoose an action:" if [ "$hash_state" = "OK" ] && [ "$signing_key_state" = "DONGLE MATCHES ROM-TRUSTED KEY" ]; then whiptail_type $BG_COLOR_MAIN_MENU --title 'Measured Integrity Report' \