Skip to content

Commit 780a9fb

Browse files
committed
kexec-unseal-key: calls new etc/functions' show_totp_until_esc() before prompting for TPM DUK passphrase
Added function show_totp_until_esc() in etc/functions: - Shows "[TIMESTAMP] | TOTP code: XXXXXX | Press Esc to continue..." (pipe-separated). - Caches TOTP for 1 second and only redraws when the second changes (avoids flicker). - Polls input every 200 ms and returns immediately on ESC, printing a blank line for separation. - Shows "TOTP unavailable" when a code cannot be fetched (initial or failure). Signed-off-by: Thierry Laurion <insurgo@riseup.net>
1 parent 70ae60f commit 780a9fb

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

initrd/bin/kexec-unseal-key

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ DEBUG "Show PCRs"
2626
DEBUG "$(pcrs)"
2727

2828
for tries in 1 2 3; do
29+
# Show updating timestamp/TOTP until user presses Esc to continue to the
30+
# passphrase prompt. This gives the user context while they prepare to
31+
# type the LUKS passphrase.
32+
show_totp_until_esc
33+
2934
read -r -s -p $'\nEnter LUKS TPM Disk Unlock Key passphrase (blank to abort): ' tpm_password
3035
echo
3136
if [ -z "$tpm_password" ]; then

initrd/etc/functions

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,3 +1550,67 @@ load_keymap() {
15501550
DO_WITH_DEBUG loadkeys /etc/board_keys.map
15511551
fi
15521552
}
1553+
1554+
# Show an updating UTC timestamp and optional TOTP on a single refreshed line
1555+
# until the user presses the Escape key. Returns 0 after ESC pressed.
1556+
# Function name: show_totp_until_esc - clearly indicates this displays the
1557+
# TOTP code and waits for the user to press Escape to continue.
1558+
show_totp_until_esc() {
1559+
local now_str status_line current_totp ch
1560+
local last_totp_time=0 last_totp=""
1561+
printf "\n" # reserve a line for updates
1562+
1563+
# Poll frequently (200ms) for responsiveness, but only refresh the
1564+
# displayed timestamp/TOTP when the displayed second changes. Cache
1565+
# the TOTP for a short interval to avoid repeated unseal calls.
1566+
local last_sec=0
1567+
while :; do
1568+
now_str=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
1569+
local now_epoch
1570+
now_epoch=$(date +%s)
1571+
local now_sec=$now_epoch
1572+
1573+
# Refresh TOTP at most once every 1 second
1574+
if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_TOTP_SKIP_QRCODE" != "y" ]; then
1575+
if [ $((now_epoch - last_totp_time)) -ge 1 ] || [ -z "$last_totp" ]; then
1576+
if current_totp=$(unseal-totp 2>/dev/null); then
1577+
last_totp="$current_totp"
1578+
last_totp_time=$now_epoch
1579+
else
1580+
# If unseal fails, clear cached value so we retry later
1581+
last_totp=""
1582+
last_totp_time=0
1583+
fi
1584+
fi
1585+
fi
1586+
1587+
# Only update display when the second changes to avoid flicker
1588+
if [ "$now_sec" -ne "$last_sec" ]; then
1589+
last_sec=$now_sec
1590+
# Build an explicit TOTP field so it's clear when no code is
1591+
# available (initial state or unseal failure).
1592+
local totp_field=""
1593+
if [ "$CONFIG_TPM" = "y" ] && [ "$CONFIG_TOTP_SKIP_QRCODE" != "y" ]; then
1594+
if [ -n "$last_totp" ]; then
1595+
totp_field=" | TOTP code: $last_totp"
1596+
else
1597+
totp_field=" | TOTP unavailable"
1598+
fi
1599+
fi
1600+
status_line="[$now_str]${totp_field} | Press Esc to continue..."
1601+
printf "\r%s\033[K" "$status_line"
1602+
fi
1603+
1604+
# Short poll for keypress (200ms). If ESC pressed, exit and return 0.
1605+
if IFS= read -r -t 0.2 -n 1 ch; then
1606+
if [ "$ch" = $'\e' ]; then
1607+
# Print an extra blank line so the next prompt appears after
1608+
# an empty line (better UX before the passphrase prompt).
1609+
printf "\n\n"
1610+
return 0
1611+
fi
1612+
# Ignore other keys and continue polling
1613+
fi
1614+
done
1615+
}
1616+

0 commit comments

Comments
 (0)