oem-factory-reset+seal-hotp nk3 hotp-verification info adaptations

- oem-factory-reset: fix strings for nk3 is from https://github.com/Nitrokey/nitrokey-hotp-verification/pull/43 is Secrets app, not Secret App singular, not App capitalized
- initrd/bin/seal-hotpkey: adapt to check nk3 Secrets App PIN counter if nk3, keep Card counters for <nk3 from https://github.com/Nitrokey/nitrokey-hotp-verification/pull/43
  - Unattended hotp_initialize output removed since we need physical presence to seal HOTP until https://github.com/Nitrokey/nitrokey-hotp-verification/issues/41 is fixed
  - Finally make seal_hotp use logic to detect if public key <1m old, use HOTP related PIN by default if counter is not <3, warn that re-ownership needs to be ran to change it since no security offered at all otherwise with HOTP
- unify format with linting tool

Tested in local tree against https://patch-diff.githubusercontent.com/raw/Nitrokey/nitrokey-hotp-verification/pull/43.patch, removing https://patch-diff.githubusercontent.com/raw/Nitrokey/nitrokey-hotp-verification/pull/46.patch
 - will revert the change above in PR once testing is over

Signed-off-by: Thierry Laurion <insurgo@riseup.net>
This commit is contained in:
Thierry Laurion 2024-12-06 09:48:28 -05:00
parent 4fd710696e
commit ebf4d1d221
No known key found for this signature in database
GPG Key ID: 9A53E1BB3FF00461
2 changed files with 82 additions and 84 deletions

View File

@ -143,13 +143,15 @@ mount_boot() {
reset_nk3_secret_app() { reset_nk3_secret_app() {
TRACE_FUNC TRACE_FUNC
# Reset Nitrokey 3 Secret App # Reset Nitrokey 3 Secrets App
if lsusb | grep -q "20a0:42b2"; then if lsusb | grep -q "20a0:42b2"; then
echo echo
echo "Resetting Nitrokey 3 Secret App PIN. Physical presence (touch) will be required" warn "Resetting Nitrokey 3 Secrets App PIN. Physical presence (touch) will be required"
#TODO, change message when https://github.com/Nitrokey/nitrokey-hotp-verification/issues/41 is fixed #TODO, change message when https://github.com/Nitrokey/nitrokey-hotp-verification/issues/41 is fixed
# Reset Nitrokey 3 secret app with PIN # Reset Nitrokey 3 secret app with PIN
/bin/hotp_verification reset "${ADMIN_PIN}" if ! /bin/hotp_verification reset "${ADMIN_PIN}"; then
whiptail_error_die "Failed to reset Nitrokey 3 Secrets App with error code $?, contact Nitrokey support"
fi
fi fi
} }
@ -552,7 +554,6 @@ gpg_key_factory_reset() {
whiptail_error_die "GPG Key factory reset failed!\n\n$ERROR" whiptail_error_die "GPG Key factory reset failed!\n\n$ERROR"
fi fi
# If Nitrokey Storage is inserted, reset AES keys as well # If Nitrokey Storage is inserted, reset AES keys as well
if lsusb | grep -q "20a0:4109" && [ -x /bin/hotp_verification ]; then if lsusb | grep -q "20a0:4109" && [ -x /bin/hotp_verification ]; then
DEBUG "Nitrokey Storage detected, resetting AES keys..." DEBUG "Nitrokey Storage detected, resetting AES keys..."
@ -560,7 +561,7 @@ gpg_key_factory_reset() {
DEBUG "Restarting scdaemon to remove possible exclusive lock of dongle" DEBUG "Restarting scdaemon to remove possible exclusive lock of dongle"
killall -9 scdaemon killall -9 scdaemon
fi fi
# Toggle forced sig (good security practice, forcing PIN request for each signature request) # Toggle forced sig (good security practice, forcing PIN request for each signature request)
if gpg --card-status | grep "Signature PIN" | grep -q "not forced"; then if gpg --card-status | grep "Signature PIN" | grep -q "not forced"; then
DEBUG "GPG toggling forcesig on since off..." DEBUG "GPG toggling forcesig on since off..."
@ -575,7 +576,7 @@ gpg_key_factory_reset() {
whiptail_error_die "GPG Key forcesig toggle on failed!\n\n$ERROR" whiptail_error_die "GPG Key forcesig toggle on failed!\n\n$ERROR"
fi fi
fi fi
# use p256 for key generation if requested # use p256 for key generation if requested
if [ "$GPG_ALGO" = "p256" ]; then if [ "$GPG_ALGO" = "p256" ]; then
{ {
@ -1388,7 +1389,7 @@ fi
#if nk3 detected, we add the NK3 Secre App PIN. Detect by product ID #if nk3 detected, we add the NK3 Secre App PIN. Detect by product ID
if lsusb | grep -q "20a0:42b2"; then if lsusb | grep -q "20a0:42b2"; then
passphrases+="Nitrokey 3 Secret App PIN: ${ADMIN_PIN}\n" passphrases+="Nitrokey 3 Secrets App PIN: ${ADMIN_PIN}\n"
fi fi
#GPG PINs output #GPG PINs output
@ -1403,7 +1404,6 @@ if [ "$GPG_GEN_KEY_IN_MEMORY" = "y" ]; then
passphrases+="GPG key material backup passphrase: ${ADMIN_PIN}\n" passphrases+="GPG key material backup passphrase: ${ADMIN_PIN}\n"
fi fi
# Show configured secrets in whiptail and loop until user confirms qr code was scanned # Show configured secrets in whiptail and loop until user confirms qr code was scanned
while true; do while true; do
whiptail --msgbox " whiptail --msgbox "

View File

@ -8,28 +8,26 @@ HOTP_SECRET="/tmp/secret/hotp.key"
HOTP_COUNTER="/boot/kexec_hotp_counter" HOTP_COUNTER="/boot/kexec_hotp_counter"
HOTP_KEY="/boot/kexec_hotp_key" HOTP_KEY="/boot/kexec_hotp_key"
mount_boot() mount_boot() {
{ TRACE_FUNC
TRACE_FUNC # Mount local disk if it is not already mounted
# Mount local disk if it is not already mounted if ! grep -q /boot /proc/mounts; then
if ! grep -q /boot /proc/mounts; then if ! mount -o ro /boot; then
if ! mount -o ro /boot; then whiptail_error --title 'ERROR' \
whiptail_error --title 'ERROR' \ --msgbox "Couldn't mount /boot.\n\nCheck the /boot device in configuration settings, or perform an OEM reset." 0 80
--msgbox "Couldn't mount /boot.\n\nCheck the /boot device in configuration settings, or perform an OEM reset." 0 80 return 1
return 1 fi
fi fi
fi
} }
TRACE_FUNC TRACE_FUNC
fatal_error() fatal_error() {
{ echo -e "\nERROR: ${1}; press Enter to continue."
echo -e "\nERROR: ${1}; press Enter to continue." read
read # get lsusb output for debugging
# get lsusb output for debugging DEBUG "lsusb output: $(lsusb)"
DEBUG "lsusb output: $(lsusb)" die "$1"
die "$1"
} }
# Use stored HOTP key branding (this might be useful after OEM reset) # Use stored HOTP key branding (this might be useful after OEM reset)
@ -41,11 +39,11 @@ fi
if [ "$CONFIG_TPM" = "y" ]; then if [ "$CONFIG_TPM" = "y" ]; then
DEBUG "Sealing HOTP secret reuses TOTP sealed secret..." DEBUG "Sealing HOTP secret reuses TOTP sealed secret..."
tpmr unseal 4d47 0,1,2,3,4,7 312 "$HOTP_SECRET" \ tpmr unseal 4d47 0,1,2,3,4,7 312 "$HOTP_SECRET" ||
|| fatal_error "Unable to unseal HOTP secret" fatal_error "Unable to unseal HOTP secret"
else else
# without a TPM, generate a secret based on the SHA-256 of the ROM # without a TPM, generate a secret based on the SHA-256 of the ROM
secret_from_rom_hash > "$HOTP_SECRET" || die "Reading ROM failed" secret_from_rom_hash >"$HOTP_SECRET" || die "Reading ROM failed"
fi fi
# Store counter in file instead of TPM for now, as it conflicts with Heads # Store counter in file instead of TPM for now, as it conflicts with Heads
@ -69,20 +67,20 @@ counter_value=1
enable_usb enable_usb
# While making sure the key is inserted, capture the status so we can check how # While making sure the key is inserted, capture the status so we can check how
# many PIN attempts remain # many PIN attempts remain
if ! hotp_token_info="$(hotp_verification info)" ; then if ! hotp_token_info="$(hotp_verification info)"; then
echo -e "\nInsert your $HOTPKEY_BRANDING and press Enter to configure it" echo -e "\nInsert your $HOTPKEY_BRANDING and press Enter to configure it"
read read
if ! hotp_token_info="$(hotp_verification info)" ; then if ! hotp_token_info="$(hotp_verification info)"; then
# don't leak key on failure # don't leak key on failure
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null shred -n 10 -z -u "$HOTP_SECRET" 2>/dev/null
fatal_error "Unable to find $HOTPKEY_BRANDING" fatal_error "Unable to find $HOTPKEY_BRANDING"
fi fi
fi fi
# Set HOTP USB Security Dongle branding based on VID # Set HOTP USB Security Dongle branding based on VID
if lsusb | grep -q "20a0:" ; then if lsusb | grep -q "20a0:"; then
HOTPKEY_BRANDING="Nitrokey" HOTPKEY_BRANDING="Nitrokey"
elif lsusb | grep -q "316d:" ; then elif lsusb | grep -q "316d:"; then
HOTPKEY_BRANDING="Librem Key" HOTPKEY_BRANDING="Librem Key"
else else
HOTPKEY_BRANDING="HOTP USB Security Dongle" HOTPKEY_BRANDING="HOTP USB Security Dongle"
@ -99,19 +97,25 @@ gpg_key_create_time="${gpg_key_create_time:-0}"
DEBUG "Signature key was created at $(date -d "@$gpg_key_create_time")" DEBUG "Signature key was created at $(date -d "@$gpg_key_create_time")"
now_date="$(date '+%s')" now_date="$(date '+%s')"
# Get the number of admin PIN retry attempts remaining # Get the number of HOTP related PIN retry attempts remaining
awk_admin_counter_regex='/^\s*Card counters: Admin (\d),.*$/' # if nk3 detected by lsusb, use different regex to get admin counter
awk_get_admin_counter="$awk_admin_counter_regex"' { print gensub('"$awk_admin_counter_regex"', "\\1", "") }' if lsusb | grep -q "20a0:42b2"; then
admin_pin_retries="$(echo "$hotp_token_info" | awk "$awk_get_admin_counter")" # Nitrokey 3: Secrets app PIN counter: 8
admin_pin_retries=$(echo "$hotp_token_info" | grep "Secrets app PIN counter:" | cut -d ':' -f 2 | tr -d ' ')
prompt_message="Secrets app"
else
admin_pin_retries=$(echo "$hotp_token_info" | grep "Card counters: Admin" | cut -d ':' -f 2 | tr -d ' ')
prompt_message="GPG Admin"
fi
admin_pin_retries="${admin_pin_retries:-0}" admin_pin_retries="${admin_pin_retries:-0}"
DEBUG "Admin PIN retry counter is $admin_pin_retries" DEBUG "HOTP related PIN retry counter is $admin_pin_retries"
#TODO: as per hotp_verification 1.6: this is 8 for nk3 and wrong. FIX
# Try using factory default admin PIN for 1 month following OEM reset to ease # Try using factory default admin PIN for 1 month following OEM reset to ease
# initial setup. But don't do it forever to encourage changing the PIN and # initial setup. But don't do it forever to encourage changing the PIN and
# so PIN attempts are not consumed by the default attempt. # so PIN attempts are not consumed by the default attempt.
admin_pin="12345678" admin_pin="12345678"
month_secs="$((30*24*60*60))" month_secs="$((30 * 24 * 60 * 60))"
admin_pin_status=1 admin_pin_status=1
if [ "$((now_date - gpg_key_create_time))" -gt "$month_secs" ]; then if [ "$((now_date - gpg_key_create_time))" -gt "$month_secs" ]; then
# Remind what the default PIN was in case it still hasn't been changed # Remind what the default PIN was in case it still hasn't been changed
@ -122,48 +126,42 @@ if [ "$((now_date - gpg_key_create_time))" -gt "$month_secs" ]; then
elif [ "$admin_pin_retries" -lt 3 ]; then elif [ "$admin_pin_retries" -lt 3 ]; then
echo "Not trying default PIN ($admin_pin), only $admin_pin_retries attempt(s) left" echo "Not trying default PIN ($admin_pin), only $admin_pin_retries attempt(s) left"
else else
hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" >/dev/null 2>&1 echo "Trying $prompt_message PIN ($admin_pin) to seal HOTP secret on $HOTPKEY_BRANDING... You may be requested to touch the dongle..."
#TODO: silence the output of hotp_initialize once https://github.com/Nitrokey/nitrokey-hotp-verification/issues/41 is fixed
#hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" >/dev/null 2>&1
hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING"
admin_pin_status="$?" admin_pin_status="$?"
fi fi
if [ "$admin_pin_status" -ne 0 ]; then if [ "$admin_pin_status" -ne 0 ]; then
# create custom message for PIN prompt based on nk3 lsusb product id # prompt user for PIN and retry
prompt_message="" echo ""
if lsusb | grep -q "20a0:42b2"; then read -s -p "Enter your $HOTPKEY_BRANDING $prompt_message PIN: " admin_pin
prompt_message="Secure App" echo -e "\n"
else
prompt_message="GPG Admin"
fi
hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING"
# prompt user for PIN and retry if [ $? -ne 0 ]; then
echo "" echo -e "\n"
read -s -p "Enter your $HOTPKEY_BRANDING $prompt_message PIN: " admin_pin read -s -p "Error setting HOTP secret, re-enter $prompt_message PIN and try again: " admin_pin
echo -e "\n" echo -e "\n"
if ! hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING"; then
hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" # don't leak key on failure
if [ $? -ne 0 ]; then shred -n 10 -z -u "$HOTP_SECRET" 2>/dev/null
echo -e "\n" if [ "$HOTPKEY_BRANDING" == "Nitrokey" ]; then
read -s -p "Error setting HOTP secret, re-enter $prompt_message PIN and try again: " admin_pin fatal_error "Setting HOTP secret failed, to reset $prompt_message PIN, redo Re-Ownership procedure, use the Nitrokey App 2 or contact Nitrokey support"
echo -e "\n" else
if ! hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" ; then fatal_error "Setting HOTP secret failed"
# don't leak key on failure fi
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null fi
if [ "$HOTPKEY_BRANDING" == "Nitrokey" ]; then fi
fatal_error "Setting HOTP secret failed, to reset $prompt_message PIN, redo Re-Ownership procedure, the Nitrokey App 2 or contact Nitrokey support" else
else # remind user to change admin password
fatal_error "Setting HOTP secret failed" warn "Factory $prompt_message default PIN detected: please change this PIN as soon as possible through OEM Factory Reset/User Re-Ownership"
fi
fi
fi
else
# remind user to change admin password
echo -e "\nWARNING: default admin PIN detected: please change this as soon as possible."
fi fi
# HOTP key no longer needed # HOTP key no longer needed
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null shred -n 10 -z -u "$HOTP_SECRET" 2>/dev/null
# Make sure our counter is incremented ahead of the next check # Make sure our counter is incremented ahead of the next check
#increment_tpm_counter $counter > /dev/null \ #increment_tpm_counter $counter > /dev/null \
@ -173,13 +171,13 @@ shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null
mount -o remount,rw /boot mount -o remount,rw /boot
counter_value=`expr $counter_value + 1` counter_value=$(expr $counter_value + 1)
echo $counter_value > $HOTP_COUNTER \ echo $counter_value >$HOTP_COUNTER ||
|| fatal_error "Unable to create hotp counter file" fatal_error "Unable to create hotp counter file"
# Store/overwrite HOTP USB Security Dongle branding found out beforehand # Store/overwrite HOTP USB Security Dongle branding found out beforehand
echo $HOTPKEY_BRANDING > $HOTP_KEY \ echo $HOTPKEY_BRANDING >$HOTP_KEY ||
|| die "Unable to store hotp key file" die "Unable to store hotp key file"
#sha256sum /tmp/counter-$counter > $HOTP_COUNTER \ #sha256sum /tmp/counter-$counter > $HOTP_COUNTER \
#|| die "Unable to create hotp counter file" #|| die "Unable to create hotp counter file"