mirror of
https://github.com/linuxboot/heads.git
synced 2025-02-08 20:10:09 +00:00
WiP: staging changes including https://github.com/linuxboot/heads/pull/1850 https://github.com/Nitrokey/nitrokey-hotp-verification/pull/43 and https://github.com/Nitrokey/nitrokey-hotp-verification/pull/46
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
This commit is contained in:
parent
4ba7cc5495
commit
abc97fe1be
@ -162,7 +162,7 @@ generate_totp_hotp()
|
||||
echo
|
||||
if [ -x /bin/hotp_verification ]; then
|
||||
if [ "$CONFIG_TOTP_SKIP_QRCODE" != y ]; then
|
||||
echo "Once you have scanned the QR code, hit Enter to configure your HOTP USB Security Dongle (e.g. Librem Key or Nitrokey)"
|
||||
echo "Once you have scanned the QR code, hit Enter to configure your HOTP USB Security dongle (e.g. Librem Key or Nitrokey)"
|
||||
read
|
||||
fi
|
||||
/bin/seal-hotpkey
|
||||
@ -644,7 +644,7 @@ TRACE_FUNC
|
||||
if [ -r /boot/kexec_hotp_key ]; then
|
||||
HOTPKEY_BRANDING="$(cat /boot/kexec_hotp_key)"
|
||||
else
|
||||
HOTPKEY_BRANDING="HOTP USB Security Dongle"
|
||||
HOTPKEY_BRANDING="HOTP USB Security dongle"
|
||||
fi
|
||||
|
||||
if [ -x /bin/hotp_verification ]; then
|
||||
|
@ -92,7 +92,7 @@ echo '+++ Building initrd'
|
||||
# pad the initramfs (dracut doesn't pad the last gz blob)
|
||||
# without this the kernel init/initramfs.c fails to read
|
||||
# the subsequent uncompressed/compressed cpio
|
||||
dd if="$INITRD" of="$SECRET_CPIO" bs=512 conv=sync ||
|
||||
dd if="$INITRD" of="$SECRET_CPIO" bs=512 conv=sync > /dev/null 2>&1 ||
|
||||
die "Failed to copy initrd to /tmp"
|
||||
|
||||
if [ "$unseal_failed" = "n" ]; then
|
||||
|
@ -143,15 +143,26 @@ mount_boot() {
|
||||
|
||||
reset_nk3_secret_app() {
|
||||
TRACE_FUNC
|
||||
# Reset Nitrokey 3 Secrets App
|
||||
# Reset Nitrokey 3 Secrets app with $ADMIN_PIN (default 12345678, or customised)
|
||||
if lsusb | grep -q "20a0:42b2"; then
|
||||
echo
|
||||
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
|
||||
warn "Resetting Nitrokey 3 Secrets App with PIN. Physical presence (touch) will be required"
|
||||
# TODO: change message when https://github.com/Nitrokey/nitrokey-hotp-verification/issues/41 is fixed
|
||||
# Reset Nitrokey 3 secret app with 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
|
||||
# Do 3 attempts to reset Nitrokey 3 Secrets App if return code is 3 (no touch)
|
||||
for attempt in 1 2 3; do
|
||||
if /bin/hotp_verification reset "${ADMIN_PIN}"; then
|
||||
echo
|
||||
return 0
|
||||
else
|
||||
error_code=$?
|
||||
if [ $error_code -eq 3 ] && [ $attempt -lt 3 ]; then
|
||||
whiptail --msgbox "Nitrokey 3 requires physical presence: touch the dongle when requested" $HEIGHT $WIDTH --title "Nk3 cecrets app reset attempt: $attempt/3"
|
||||
else
|
||||
whiptail_error_die "Nitrokey 3 secrets app reset failed with error:$error_code. Contact Nitrokey support"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
@ -323,7 +334,7 @@ generate_inmemory_p256_master_and_subkeys() {
|
||||
keytocard_subkeys_to_smartcard() {
|
||||
TRACE_FUNC
|
||||
|
||||
#make sure usb ready and USB Security Dongle ready to communicate with
|
||||
#make sure usb ready and USB Security dongle ready to communicate with
|
||||
enable_usb
|
||||
enable_usb_storage
|
||||
gpg --card-status >/dev/null 2>&1 || die "Error getting GPG card status"
|
||||
@ -541,7 +552,7 @@ gpg_key_factory_reset() {
|
||||
reset_nk3_secret_app
|
||||
|
||||
# Factory reset GPG card
|
||||
echo "GPG factory reset of USB Security Dongle's smartcard..."
|
||||
echo "GPG factory reset of USB Security dongle's OpenPGP smartcard..."
|
||||
{
|
||||
echo admin # admin menu
|
||||
echo factory-reset # factory reset smartcard
|
||||
@ -595,7 +606,7 @@ gpg_key_factory_reset() {
|
||||
>/tmp/gpg_card_edit_output 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
ERROR=$(cat /tmp/gpg_card_edit_output)
|
||||
whiptail_error_die "Setting key to NIST-P256 in USB Security Dongle failed."
|
||||
whiptail_error_die "Setting key to NIST-P256 in USB Security dongle failed."
|
||||
fi
|
||||
# fallback to RSA key generation by default
|
||||
elif [ "$GPG_ALGO" = "RSA" ]; then
|
||||
@ -617,7 +628,7 @@ gpg_key_factory_reset() {
|
||||
>/tmp/gpg_card_edit_output 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
ERROR=$(cat /tmp/gpg_card_edit_output)
|
||||
whiptail_error_die "Setting key attributed to RSA ${RSA_KEY_LENGTH} bits in USB Security Dongle failed."
|
||||
whiptail_error_die "Setting key attributed to RSA ${RSA_KEY_LENGTH} bits in USB Security dongle failed."
|
||||
fi
|
||||
else
|
||||
#Unknown GPG_ALGO
|
||||
@ -631,7 +642,7 @@ generate_OEM_gpg_keys() {
|
||||
TRACE_FUNC
|
||||
|
||||
#This function simply generates subkeys in smartcard following smarcard config from gpg_key_factory_reset
|
||||
echo "Generating GPG keys in USB Security Dongle's smartcard..."
|
||||
echo "Generating GPG keys in USB Security dongle's OpenPGP smartcard..."
|
||||
{
|
||||
echo admin # admin menu
|
||||
echo generate # generate keys
|
||||
@ -645,6 +656,11 @@ generate_OEM_gpg_keys() {
|
||||
echo ${USER_PIN_DEF} # Default user PIN since we just factory reset
|
||||
} | DO_WITH_DEBUG gpg --command-fd=0 --status-fd=2 --pinentry-mode=loopback --card-edit \
|
||||
>/tmp/gpg_card_edit_output 2>&1
|
||||
#This outputs to console \
|
||||
# "gpg: checking the trustdb"
|
||||
# "gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model"
|
||||
# "gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u"
|
||||
#TODO: Suppress this output to console (stdout shown in DEBUG mode)?
|
||||
if [ $? -ne 0 ]; then
|
||||
ERROR=$(cat /tmp/gpg_card_edit_output)
|
||||
whiptail_error_die "GPG Key automatic keygen failed!\n\n$ERROR"
|
||||
@ -704,7 +720,7 @@ generate_checksums() {
|
||||
tpmr counter_create \
|
||||
-pwdc '' \
|
||||
-la -3135106223 |
|
||||
tee /tmp/counter ||
|
||||
tee /tmp/counter >/dev/null 2>&1 ||
|
||||
whiptail_error_die "Unable to create TPM counter"
|
||||
TPM_COUNTER=$(cut -d: -f1 </tmp/counter)
|
||||
|
||||
@ -850,14 +866,14 @@ report_integrity_measurements() {
|
||||
enable_usb
|
||||
for attempt in 1 2 3; do
|
||||
if ! hotp_verification info >/dev/null 2>&1; then
|
||||
whiptail_warning --title "WARNING: Please insert your HOTP enabled USB Security Dongle (Attempt $attempt/3)" --msgbox "Your HOTP enabled USB Security Dongle was not detected.\n\nPlease remove it and insert it again." 0 80
|
||||
whiptail_warning --title "WARNING: Please insert your HOTP enabled USB Security dongle (Attempt $attempt/3)" --msgbox "Your HOTP enabled USB Security dongle was not detected.\n\nPlease remove it and insert it again." 0 80
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $attempt -eq 3 ]; then
|
||||
die "No HOTP enabled USB Security Dongle detected. Please disable 'CONFIG_HOTPKEY' in the board config and rebuild."
|
||||
die "No HOTP enabled USB Security dongle detected. Please disable 'CONFIG_HOTPKEY' in the board config and rebuild."
|
||||
fi
|
||||
|
||||
# Don't output HOTP codes to screen, so as to make replay attacks harder
|
||||
@ -872,7 +888,7 @@ report_integrity_measurements() {
|
||||
BG_COLOR_MAIN_MENU="error"
|
||||
;;
|
||||
*)
|
||||
HOTP="Error checking code, Insert USB Security Dongle and retry"
|
||||
HOTP="Error checking code, Insert USB Security dongle and retry"
|
||||
BG_COLOR_MAIN_MENU="warning"
|
||||
;;
|
||||
esac
|
||||
@ -997,21 +1013,21 @@ if [ "$use_defaults" == "n" -o "$use_defaults" == "N" ]; then
|
||||
; then
|
||||
GPG_GEN_KEY_IN_MEMORY="y"
|
||||
echo " ++++ Master key and subkeys will be generated in memory, backed up to dedicated LUKS container +++"
|
||||
echo -e -n "Would you like in-memory generated subkeys to be copied to USB Security Dongle's smartcard?\n (Highly recommended so the smartcard is used on daily basis and backup is kept safe, but not required) [Y/n]: "
|
||||
echo -e -n "Would you like in-memory generated subkeys to be copied to USB Security dongle's OpenPGP smartcard?\n (Highly recommended so the smartcard is used on daily basis and backup is kept safe, but not required) [Y/n]: "
|
||||
read -n 1 prompt_output
|
||||
echo
|
||||
if [ "$prompt_output" == "n" \
|
||||
-o "$prompt_output" == "N" ]; then
|
||||
warn "Subkeys will NOT be copied to USB Security Dongle's smartcard"
|
||||
warn "Subkeys will NOT be copied to USB Security dongle's OpenPGP smartcard"
|
||||
warn "Your GPG key material backup thumb drive should be cloned to a second thumb drive for redundancy for production environements"
|
||||
GPG_GEN_KEY_IN_MEMORY_COPY_TO_SMARTCARD="n"
|
||||
else
|
||||
echo "++++ Subkeys will be copied to USB Security Dongle's smartcard ++++"
|
||||
echo "++++ Subkeys will be copied to USB Security dongle's OpenPGP smartcard ++++"
|
||||
warn "Please keep your GPG key material backup thumb drive safe"
|
||||
GPG_GEN_KEY_IN_MEMORY_COPY_TO_SMARTCARD="y"
|
||||
fi
|
||||
else
|
||||
echo "GPG key material will be generated on USB Security Dongle's smartcard without backup"
|
||||
echo "GPG key material will be generated on USB Security dongle's OpenPGP smartcard without backup"
|
||||
GPG_GEN_KEY_IN_MEMORY="n"
|
||||
GPG_GEN_KEY_IN_MEMORY_COPY_TO_SMARTCARD="n"
|
||||
fi
|
||||
@ -1177,24 +1193,24 @@ if [ "$GPG_GEN_KEY_IN_MEMORY" = "n" ]; then
|
||||
fi
|
||||
else
|
||||
GPG_EXPORT=0
|
||||
# needed for USB Security Dongle below and is ensured via mount-usb in case of GPG_EXPORT=1
|
||||
# needed for USB Security dongle below and is ensured via mount-usb in case of GPG_EXPORT=1
|
||||
enable_usb
|
||||
fi
|
||||
fi
|
||||
|
||||
# ensure USB Security Dongle connected if GPG_GEN_KEY_IN_MEMORY=n or if GPG_GEN_KEY_IN_MEMORY_COPY_TO_SMARTCARD=y
|
||||
# ensure USB Security dongle connected if GPG_GEN_KEY_IN_MEMORY=n or if GPG_GEN_KEY_IN_MEMORY_COPY_TO_SMARTCARD=y
|
||||
if [ "$GPG_GEN_KEY_IN_MEMORY" = "n" -o "$GPG_GEN_KEY_IN_MEMORY_COPY_TO_SMARTCARD" = "y" ]; then
|
||||
echo -e "\nChecking for USB Security Dongle...\n"
|
||||
echo -e "\nChecking for USB Security dongle...\n"
|
||||
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 USB Security dongle; \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 USB Security dongle:\n\n${ERROR}"
|
||||
fi
|
||||
fi
|
||||
|
||||
#Now that USB Security Dongle is detected, we can check its capabilities and limitations
|
||||
#Now that USB Security dongle is detected, we can check its capabilities and limitations
|
||||
usb_security_token_capabilities_check
|
||||
fi
|
||||
|
||||
@ -1266,7 +1282,7 @@ if [ "$GPG_GEN_KEY_IN_MEMORY" = "y" ]; then
|
||||
fi
|
||||
else
|
||||
#Generate GPG key and subkeys on smartcard only
|
||||
echo -e "\nResetting USB Security Dongle's GPG smartcard...\n(this will take around 3 minutes...)\n"
|
||||
echo -e "\nResetting USB Security dongle's GPG smartcard...\n(this will take around 3 minutes...)\n"
|
||||
gpg_key_factory_reset
|
||||
generate_OEM_gpg_keys
|
||||
fi
|
||||
@ -1389,7 +1405,7 @@ fi
|
||||
|
||||
#if nk3 detected, we add the NK3 Secre App PIN. Detect by product ID
|
||||
if lsusb | grep -q "20a0:42b2"; then
|
||||
passphrases+="Nitrokey 3 Secrets App PIN: ${ADMIN_PIN}\n"
|
||||
passphrases+="Nitrokey 3 Secrets app PIN: ${ADMIN_PIN}\n"
|
||||
fi
|
||||
|
||||
#GPG PINs output
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
# Retrieve the sealed TOTP secret and initialize a USB Security Dongle with it
|
||||
# Retrieve the sealed TOTP secret and initialize a USB Security dongle with it
|
||||
|
||||
. /etc/functions
|
||||
. /etc/gui_functions
|
||||
@ -34,7 +34,7 @@ fatal_error() {
|
||||
if [ -r /boot/kexec_hotp_key ]; then
|
||||
HOTPKEY_BRANDING="$(cat /boot/kexec_hotp_key)"
|
||||
else
|
||||
HOTPKEY_BRANDING="HOTP USB Security Dongle"
|
||||
HOTPKEY_BRANDING="HOTP USB Security dongle"
|
||||
fi
|
||||
|
||||
if [ "$CONFIG_TPM" = "y" ]; then
|
||||
@ -77,13 +77,13 @@ if ! hotp_token_info="$(hotp_verification info)"; then
|
||||
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
|
||||
HOTPKEY_BRANDING="Nitrokey"
|
||||
elif lsusb | grep -q "316d:"; then
|
||||
HOTPKEY_BRANDING="Librem Key"
|
||||
else
|
||||
HOTPKEY_BRANDING="HOTP USB Security Dongle"
|
||||
HOTPKEY_BRANDING="HOTP USB Security dongle"
|
||||
fi
|
||||
|
||||
# Truncate the secret if it is longer than the maximum HOTP secret
|
||||
@ -175,7 +175,7 @@ counter_value=$(expr $counter_value + 1)
|
||||
echo $counter_value >$HOTP_COUNTER ||
|
||||
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 ||
|
||||
die "Unable to store hotp key file"
|
||||
|
||||
|
@ -29,7 +29,6 @@ else
|
||||
. /etc/config
|
||||
fi
|
||||
|
||||
|
||||
# Busybox xxd lacks -r, and we get hex dumps from TPM1 commands. This converts
|
||||
# a hex dump to binary data using sed and printf
|
||||
hex2bin() {
|
||||
@ -258,7 +257,7 @@ tpm2_extend() {
|
||||
esac
|
||||
done
|
||||
tpm2 pcrextend "$index:sha256=$hash"
|
||||
LOG $(tpm2 pcrread "sha256:$index" 2>&1)
|
||||
LOG $(tpm2 pcrread "sha256:$index" 2>&1)
|
||||
|
||||
TRACE_FUNC
|
||||
DEBUG "TPM: Extended PCR[$index] with hash $hash"
|
||||
@ -307,7 +306,7 @@ tpm1_counter_create() {
|
||||
# other parameters for TPM1 are passed directly, and TPM2 mimics the
|
||||
# TPM1 interface.
|
||||
prompt_tpm_owner_password
|
||||
if ! tpm counter_create -pwdo "$(cat "/tmp/secret/tpm_owner_password")" "$@"; then
|
||||
if ! tpm counter_create -pwdo "$(cat "/tmp/secret/tpm_owner_password")" "$@" >/dev/null 2>&1; then
|
||||
DEBUG "Failed to create counter from tpm1_counter_create. Wiping /tmp/secret/tpm_owner_password"
|
||||
shred -n 10 -z -u /tmp/secret/tpm_owner_password
|
||||
die "Unable to create counter from tpm1_counter_create"
|
||||
@ -334,7 +333,7 @@ tpm2_counter_create() {
|
||||
prompt_tpm_owner_password
|
||||
rand_index="1$(dd if=/dev/urandom bs=1 count=3 2>/dev/null | xxd -pc3)"
|
||||
tpm2 nvdefine -C o -s 8 -a "ownerread|authread|authwrite|nt=1" \
|
||||
-P "$(tpm2_password_hex "$(cat "/tmp/secret/tpm_owner_password")")" "0x$rand_index" >/dev/console ||
|
||||
-P "$(tpm2_password_hex "$(cat "/tmp/secret/tpm_owner_password")")" "0x$rand_index" >/dev/null 2>&1 ||
|
||||
{
|
||||
DEBUG "Failed to create counter from tpm2_counter_create. Wiping /tmp/secret/tpm_owner_password"
|
||||
shred -n 10 -z -u /tmp/secret/tpm_owner_password
|
||||
@ -357,12 +356,13 @@ tpm2_startsession() {
|
||||
tpm2 flushcontext -Q \
|
||||
--saved-session ||
|
||||
die "tpm2_flushcontext: unable to flush saved session"
|
||||
tpm2 readpublic -Q -c "$PRIMARY_HANDLE" -t "$PRIMARY_HANDLE_FILE"
|
||||
#TODO: readpublic cannot be silenced even if redirected to /dev/null with both stderr and stdout redirected?
|
||||
tpm2 readpublic -Q -c "$PRIMARY_HANDLE" -t "$PRIMARY_HANDLE_FILE" >/dev/null 2>&1
|
||||
#TODO: do the right thing to not have to suppress "WARN: check public portion the tpmkey manually" see https://github.com/linuxboot/heads/pull/1630#issuecomment-2075120429
|
||||
tpm2 startauthsession -Q -c "$PRIMARY_HANDLE_FILE" --hmac-session -S "$ENC_SESSION_FILE" > /dev/null 2>&1
|
||||
tpm2 startauthsession -Q -c "$PRIMARY_HANDLE_FILE" --hmac-session -S "$ENC_SESSION_FILE" >/dev/null 2>&1
|
||||
#TODO: do the right thing to not have to suppress "WARN: check public portion the tpmkey manually" see https://github.com/linuxboot/heads/pull/1630#issuecomment-2075120429
|
||||
tpm2 startauthsession -Q -c "$PRIMARY_HANDLE_FILE" --hmac-session -S "$DEC_SESSION_FILE" > /dev/null 2>&1
|
||||
tpm2 sessionconfig -Q --disable-encrypt "$DEC_SESSION_FILE"
|
||||
tpm2 startauthsession -Q -c "$PRIMARY_HANDLE_FILE" --hmac-session -S "$DEC_SESSION_FILE" >/dev/null 2>&1
|
||||
tpm2 sessionconfig -Q --disable-encrypt "$DEC_SESSION_FILE" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Use cleanup_session() with at_exit to release a TPM2 session and delete the
|
||||
@ -412,7 +412,7 @@ tpm1_destroy() {
|
||||
index="$1" # Index of the sealed file
|
||||
size="$2" # Size of zeroes to overwrite for TPM1
|
||||
|
||||
dd if=/dev/zero bs="$size" count=1 of=/tmp/wipe-totp-zero > /dev/null 2>&1
|
||||
dd if=/dev/zero bs="$size" count=1 of=/tmp/wipe-totp-zero >/dev/null 2>&1
|
||||
tpm nv_writevalue -in "$index" -if /tmp/wipe-totp-zero ||
|
||||
die "Unable to wipe sealed secret from TPM NVRAM"
|
||||
}
|
||||
@ -502,7 +502,7 @@ tpm1_seal() {
|
||||
pcrl="$3" #0,1,2,3,4,5,6,7 (does not include algorithm prefix)
|
||||
pcrf="$4"
|
||||
sealed_size="$5"
|
||||
pass="$6" # May be empty to seal with no password
|
||||
pass="$6" # May be empty to seal with no password
|
||||
tpm_owner_password="$7" # Owner password - will prompt if needed and not empty
|
||||
|
||||
sealed_file="$SECRET_DIR/tpm1_seal_sealed.bin"
|
||||
@ -512,7 +512,6 @@ tpm1_seal() {
|
||||
|
||||
DEBUG "tpm1_seal arguments: file=$file index=$index pcrl=$pcrl pcrf=$pcrf sealed_size=$sealed_size pass=$(mask_param "$pass") tpm_password=$(mask_param "$tpm_password")"
|
||||
|
||||
|
||||
# If a password was given, add it to the policy arguments
|
||||
if [ "$pass" ]; then
|
||||
POLICY_ARGS+=(-pwdd "$pass")
|
||||
@ -534,7 +533,7 @@ tpm1_seal() {
|
||||
-of "$sealed_file" \
|
||||
-hk 40000000 \
|
||||
"${POLICY_ARGS[@]}"
|
||||
|
||||
|
||||
# try it without the TPM Owner Password first
|
||||
if ! tpm nv_writevalue -in "$index" -if "$sealed_file"; then
|
||||
# to create an nvram space we need the TPM Owner Password
|
||||
@ -605,9 +604,22 @@ tpm2_unseal() {
|
||||
UNSEAL_PASS_SUFFIX="+$(tpm2_password_hex "$pass")"
|
||||
fi
|
||||
|
||||
tpm2 unseal -Q -c "$handle" -p "session:$POLICY_SESSION$UNSEAL_PASS_SUFFIX" \
|
||||
-S "$ENC_SESSION_FILE" >"$file"
|
||||
# tpm2 unseal will write the unsealed data to stdout and any errors to
|
||||
# stderr. We capture the unsealed data to $file, but still log the errors for quiet mode.
|
||||
# In case of unseal error, caller will also report on TOTP not being able to be unsealed.
|
||||
TMP_ERR_FILE=$(mktemp)
|
||||
if ! tpm2 unseal -Q -c "$handle" -p "session:$POLICY_SESSION$UNSEAL_PASS_SUFFIX" \
|
||||
-S "$ENC_SESSION_FILE" >"$file" 2>"$TMP_ERR_FILE"; then
|
||||
# Log the contents of the temporary error file
|
||||
while IFS= read -r line; do
|
||||
LOG "tpm2 stderr: $line"
|
||||
done <"$TMP_ERR_FILE"
|
||||
rm -f "$TMP_ERR_FILE"
|
||||
die "Unable to unseal secret from TPM NVRAM with tpm2 unseal"
|
||||
fi
|
||||
rm -f "$TMP_ERR_FILE"
|
||||
}
|
||||
|
||||
tpm1_unseal() {
|
||||
TRACE_FUNC
|
||||
index="$1"
|
||||
@ -650,15 +662,15 @@ tpm2_reset() {
|
||||
# output TPM Owner Password to a file to be reused in this boot session until recovery shell/reboot
|
||||
DEBUG "Caching TPM Owner Password to $SECRET_DIR/tpm_owner_password"
|
||||
echo -n "$tpm_owner_password" >"$SECRET_DIR/tpm_owner_password"
|
||||
tpm2 clear -c platform > /dev/null 2>&1 || LOG "Unable to clear TPM on platform hierarchy"
|
||||
tpm2 changeauth -c owner "$(tpm2_password_hex "$tpm_owner_password")" > /dev/null 2>&1 || LOG "Unable to change owner password"
|
||||
tpm2 changeauth -c endorsement "$(tpm2_password_hex "$tpm_owner_password")" > /dev/null 2>&1 || LOG "Unable to change endorsement password"
|
||||
tpm2 clear -c platform >/dev/null 2>&1 || LOG "Unable to clear TPM on platform hierarchy"
|
||||
tpm2 changeauth -c owner "$(tpm2_password_hex "$tpm_owner_password")" >/dev/null 2>&1 || LOG "Unable to change owner password"
|
||||
tpm2 changeauth -c endorsement "$(tpm2_password_hex "$tpm_owner_password")" >/dev/null 2>&1 || LOG "Unable to change endorsement password"
|
||||
tpm2 createprimary -C owner -g sha256 -G "${CONFIG_PRIMARY_KEY_TYPE:-rsa}" \
|
||||
-c "$SECRET_DIR/primary.ctx" -P "$(tpm2_password_hex "$tpm_owner_password")" > /dev/null 2>&1 || LOG "Unable to create primary key"
|
||||
-c "$SECRET_DIR/primary.ctx" -P "$(tpm2_password_hex "$tpm_owner_password")" >/dev/null 2>&1 || LOG "Unable to create primary key"
|
||||
tpm2 evictcontrol -C owner -c "$SECRET_DIR/primary.ctx" "$PRIMARY_HANDLE" \
|
||||
-P "$(tpm2_password_hex "$tpm_owner_password")" > /dev/null 2>&1 || LOG "Unable to evict primary key"
|
||||
shred -u "$SECRET_DIR/primary.ctx" > /dev/null 2>&1
|
||||
tpm2_startsession > /dev/null 2>&1 || LOG "Unable to start session"
|
||||
-P "$(tpm2_password_hex "$tpm_owner_password")" >/dev/null 2>&1 || LOG "Unable to evict primary key"
|
||||
shred -u "$SECRET_DIR/primary.ctx" >/dev/null 2>&1
|
||||
tpm2_startsession >/dev/null 2>&1 || LOG "Unable to start session"
|
||||
|
||||
# Set the dictionary attack parameters. TPM2 defaults vary widely, we
|
||||
# want consistent behavior on any TPM.
|
||||
@ -681,7 +693,7 @@ tpm2_reset() {
|
||||
--max-tries=10 \
|
||||
--recovery-time=3600 \
|
||||
--lockout-recovery-time=0 \
|
||||
--auth="session:$ENC_SESSION_FILE" > /dev/null 2>&1 || LOG "Unable to set dictionary lockout parameters"
|
||||
--auth="session:$ENC_SESSION_FILE" >/dev/null 2>&1 || LOG "Unable to set dictionary lockout parameters"
|
||||
|
||||
# Set a random DA lockout password, so the DA lockout can't be cleared
|
||||
# with a password. Heads doesn't offer dictionary attach reset, instead
|
||||
@ -690,7 +702,7 @@ tpm2_reset() {
|
||||
# The default lockout password is empty, so we must set this, and we
|
||||
# don't need to provide any auth (use the default empty password).
|
||||
tpm2 changeauth -Q -c lockout \
|
||||
"hex:$(dd if=/dev/urandom bs=32 count=1 status=none 2>/dev/null | xxd -p | tr -d ' \n')" > /dev/null 2>&1 || LOG "Unable to set lockout password"
|
||||
"hex:$(dd if=/dev/urandom bs=32 count=1 status=none 2>/dev/null | xxd -p | tr -d ' \n')" >/dev/null 2>&1 || LOG "Unable to set lockout password"
|
||||
}
|
||||
tpm1_reset() {
|
||||
TRACE_FUNC
|
||||
@ -700,17 +712,17 @@ tpm1_reset() {
|
||||
DEBUG "Caching TPM Owner Password to $SECRET_DIR/tpm_owner_password"
|
||||
echo -n "$tpm_owner_password" >"$SECRET_DIR/tpm_owner_password"
|
||||
# Make sure the TPM is ready to be reset
|
||||
tpm physicalpresence -s > /dev/null 2>&1 || LOG "Unable to assert physical presence"
|
||||
tpm physicalenable > /dev/null 2>&1 || >LOG "Unable to enable TPM"
|
||||
tpm physicalsetdeactivated -c > /dev/null 2>&1 || LOG "Unable to deactivate TPM"
|
||||
tpm forceclear -pwdo "$tpm_owner_password" > /dev/null 2>&1 || LOG "Unable to clear TPM"
|
||||
tpm physicalenable > /dev/null 2>&1 || LOG "Unable to enable TPM"
|
||||
tpm takeown -pwdo "$tpm_owner_password" > /dev/null 2>&1 || LOG "Unable to take ownership of TPM"
|
||||
tpm physicalpresence -s >/dev/null 2>&1 || LOG "Unable to assert physical presence"
|
||||
tpm physicalenable >/dev/null 2>&1 || LOG "Unable to enable TPM"
|
||||
tpm physicalsetdeactivated -c >/dev/null 2>&1 || LOG "Unable to deactivate TPM"
|
||||
tpm forceclear -pwdo "$tpm_owner_password" >/dev/null 2>&1 || LOG "Unable to clear TPM"
|
||||
tpm physicalenable >/dev/null 2>&1 || LOG "Unable to enable TPM"
|
||||
tpm takeown -pwdo "$tpm_owner_password" >/dev/null 2>&1 || LOG "Unable to take ownership of TPM"
|
||||
|
||||
# And now turn it all back on
|
||||
tpm physicalpresence -s > /dev/null 2>&1 || LOG "Unable to assert physical presence"
|
||||
tpm physicalenable > /dev/null 2>&1 || LOG "Unable to enable TPM"
|
||||
tpm physicalsetdeactivated -c > /dev/null 2>&1 || LOG "Unable to deactivate TPM"
|
||||
tpm physicalpresence -s >/dev/null 2>&1 || LOG "Unable to assert physical presence"
|
||||
tpm physicalenable >/dev/null 2>&1 || LOG "Unable to enable TPM"
|
||||
tpm physicalsetdeactivated -c >/dev/null 2>&1 || LOG "Unable to deactivate TPM physical presence requirement"
|
||||
}
|
||||
|
||||
# Perform final cleanup before boot and lock the platform heirarchy.
|
||||
@ -784,7 +796,7 @@ if [ "$CONFIG_TPM2_TOOLS" != "y" ]; then
|
||||
DEBUG "TPM: Will extend PCR[$3] with hash of filename $string"
|
||||
hash="$(echo -n "$5" | sha1sum | cut -d' ' -f1)"
|
||||
fi
|
||||
|
||||
|
||||
TRACE_FUNC
|
||||
LOG "TPM: Extending PCR[$3] with hash $hash"
|
||||
DO_WITH_DEBUG exec tpm "$@"
|
||||
|
@ -147,7 +147,7 @@ confirm_gpg_card() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# setup the USB so we can reach the USB Security Dongle's smartcard
|
||||
# setup the USB so we can reach the USB Security dongle's OpenPGP smartcard
|
||||
enable_usb
|
||||
|
||||
echo -e "\nVerifying presence of GPG card...\n"
|
||||
|
@ -181,7 +181,7 @@ fi
|
||||
# Setup recovery serial shell
|
||||
if [ ! -z "$CONFIG_BOOT_RECOVERY_SERIAL" ]; then
|
||||
stty -F "$CONFIG_BOOT_RECOVERY_SERIAL" 115200
|
||||
pause_recovery 'Console recovery shell' \
|
||||
pause_recovery 'Serial console recovery shell' \
|
||||
< "$CONFIG_BOOT_RECOVERY_SERIAL" \
|
||||
> "$CONFIG_BOOT_RECOVERY_SERIAL" 2>&1 &
|
||||
fi
|
||||
@ -207,6 +207,7 @@ if [ "$boot_option" = "r" ]; then
|
||||
exit
|
||||
elif [ "$boot_option" = "o" ]; then
|
||||
# Launch OEM Factory Reset mode
|
||||
echo -e "***** Entering OEM Factory Reset mode\n" > /dev/tty0
|
||||
oem-factory-reset --mode oem
|
||||
# just in case...
|
||||
exit
|
||||
|
@ -2,12 +2,12 @@ modules-$(CONFIG_HOTPKEY) += hotp-verification
|
||||
|
||||
hotp-verification_depends := libusb $(musl_dep)
|
||||
|
||||
# v1.6
|
||||
hotp-verification_version := e9050e0c914e7a8ffef5d1c82a014e0e2bf79346
|
||||
# v1.6 + patches for nk3 reset + info fixes (no version bump yet)
|
||||
hotp-verification_version := 05ac293dfef8abe463ccea8f248066e8686ce62d
|
||||
hotp-verification_dir := hotp-verification-$(hotp-verification_version)
|
||||
hotp-verification_tar := nitrokey-hotp-verification-$(hotp-verification_version).tar.gz
|
||||
hotp-verification_url := https://github.com/Nitrokey/nitrokey-hotp-verification/archive/$(hotp-verification_version).tar.gz
|
||||
hotp-verification_hash := 480c978d3585eee73b9aa5186b471d4caeeeeba411217e1544eef7cfd90312ac
|
||||
hotp-verification_hash := 1095640fdae77938ce2d2ce294c7ecb8c27b77060975af8d838b6fd056ed5068
|
||||
|
||||
hotp-verification_target := \
|
||||
$(MAKE_JOBS) \
|
||||
|
@ -1,7 +1,7 @@
|
||||
From de355ed93ba50280bf377772082b76b7a2285185 Mon Sep 17 00:00:00 2001
|
||||
From 45fb0932c3a45978d894fcaae2c242ffa93516f2 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= <sosthene@nitrokey.com>
|
||||
Date: Mon, 25 Nov 2024 17:04:47 +0100
|
||||
Subject: [PATCH 1/3] Add reset command for nitrokey 3
|
||||
Subject: [PATCH 1/4] Add reset command for nitrokey 3
|
||||
|
||||
---
|
||||
src/main.c | 10 ++++++++--
|
||||
@ -10,7 +10,7 @@ Subject: [PATCH 1/3] Add reset command for nitrokey 3
|
||||
3 files changed, 50 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/main.c b/src/main.c
|
||||
index 059069e..b80b71d 100644
|
||||
index ed26932..41b1692 100644
|
||||
--- a/src/main.c
|
||||
+++ b/src/main.c
|
||||
@@ -21,6 +21,7 @@
|
||||
@ -20,8 +20,8 @@ index 059069e..b80b71d 100644
|
||||
+#include "operations_ccid.h"
|
||||
#include "return_codes.h"
|
||||
#include "utils.h"
|
||||
#include "version.h"
|
||||
@@ -134,8 +135,13 @@ int parse_cmd_and_run(int argc, char *const *argv) {
|
||||
#include "operations_ccid.h"
|
||||
@@ -161,8 +162,13 @@ int parse_cmd_and_run(int argc, char *const *argv) {
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
@ -38,7 +38,7 @@ index 059069e..b80b71d 100644
|
||||
default:
|
||||
break;
|
||||
diff --git a/src/operations_ccid.c b/src/operations_ccid.c
|
||||
index eb46124..574155d 100644
|
||||
index 1ca6f54..cdaf940 100644
|
||||
--- a/src/operations_ccid.c
|
||||
+++ b/src/operations_ccid.c
|
||||
@@ -32,6 +32,47 @@
|
||||
@ -90,47 +90,48 @@ index eb46124..574155d 100644
|
||||
TLV tlvs[] = {
|
||||
{
|
||||
diff --git a/src/operations_ccid.h b/src/operations_ccid.h
|
||||
index b26b3c7..ec0070c 100644
|
||||
index 77a6fdc..20415c0 100644
|
||||
--- a/src/operations_ccid.h
|
||||
+++ b/src/operations_ccid.h
|
||||
@@ -11,6 +11,7 @@ int authenticate_or_set_ccid(struct Device *dev, const char *admin_PIN);
|
||||
int set_secret_on_device_ccid(struct Device *dev, const char *admin_PIN, const char *OTP_secret_base32, const uint64_t hotp_counter);
|
||||
@@ -12,6 +12,7 @@ int set_secret_on_device_ccid(struct Device *dev, const char *admin_PIN, const c
|
||||
int verify_code_ccid(struct Device *dev, const uint32_t code_to_verify);
|
||||
int status_ccid(libusb_device_handle *handle, int *attempt_counter, uint16_t *firmware_version, uint32_t *serial_number);
|
||||
int status_ccid(libusb_device_handle *handle, struct FullResponseStatus *full_response);
|
||||
int nk3_change_pin(struct Device *dev, const char *old_pin, const char*new_pin);
|
||||
+int nk3_reset(struct Device *dev);
|
||||
|
||||
|
||||
#endif//NITROKEY_HOTP_VERIFICATION_OPERATIONS_CCID_H
|
||||
|
||||
From 8425e8c622138aef9ab207119e14f7cbedd40175 Mon Sep 17 00:00:00 2001
|
||||
From 12ba32eb823a3d895ce77052022f8da3e40172ca Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= <sosthene@nitrokey.com>
|
||||
Date: Mon, 2 Dec 2024 10:29:59 +0100
|
||||
Subject: [PATCH 2/3] Add optional new pin when resetting
|
||||
Subject: [PATCH 2/4] Add optional new pin when resetting
|
||||
|
||||
---
|
||||
src/main.c | 9 +++++----
|
||||
src/operations_ccid.c | 6 +++++-
|
||||
src/operations_ccid.h | 5 ++++-
|
||||
3 files changed, 14 insertions(+), 6 deletions(-)
|
||||
src/main.c | 11 +++++++----
|
||||
src/operations_ccid.c | 6 +++++-
|
||||
src/operations_ccid.h | 5 ++++-
|
||||
3 files changed, 16 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/main.c b/src/main.c
|
||||
index b80b71d..3f4a1cc 100644
|
||||
index 41b1692..84c0afe 100644
|
||||
--- a/src/main.c
|
||||
+++ b/src/main.c
|
||||
@@ -38,9 +38,10 @@ void print_help(char *app_name) {
|
||||
"\t%s info\n"
|
||||
"\t%s version\n"
|
||||
@@ -41,8 +41,11 @@ void print_help(char *app_name) {
|
||||
"\t%s check <HOTP CODE>\n"
|
||||
- "\t%s regenerate <ADMIN PIN>\n"
|
||||
"\t%s regenerate <ADMIN PIN>\n"
|
||||
"\t%s set <BASE32 HOTP SECRET> <ADMIN PIN> [COUNTER]\n"
|
||||
- "\t%s nk3-change-pin <old-pin> <new-pin>\n",
|
||||
- app_name, app_name, app_name, app_name, app_name, app_name, app_name);
|
||||
+ "\t%s nk3-change-pin <old-pin> <new-pin>\n"
|
||||
+ "\t%s reset [ADMIN PIN]\n"
|
||||
+ "\t%s regenerate\n"
|
||||
"\t%s set <BASE32 HOTP SECRET> <ADMIN PIN> [COUNTER]\n",
|
||||
- app_name, app_name, app_name, app_name, app_name, app_name);
|
||||
+ app_name, app_name, app_name, app_name, app_name, app_name, app_name);
|
||||
+ "\t%s set <BASE32 HOTP SECRET> <ADMIN PIN> [COUNTER]\n",
|
||||
+ app_name, app_name, app_name, app_name, app_name, app_name, app_name, app_name, app_name, app_name);
|
||||
}
|
||||
|
||||
|
||||
@@ -136,8 +137,8 @@ int parse_cmd_and_run(int argc, char *const *argv) {
|
||||
@@ -163,8 +166,8 @@ int parse_cmd_and_run(int argc, char *const *argv) {
|
||||
break;
|
||||
case 'r':
|
||||
if (strncmp(argv[1], "reset", 15) == 0) {
|
||||
@ -142,7 +143,7 @@ index b80b71d..3f4a1cc 100644
|
||||
if (argc != 3) break;
|
||||
res = regenerate_AES_key(&dev, argv[2]);
|
||||
diff --git a/src/operations_ccid.c b/src/operations_ccid.c
|
||||
index 574155d..07834ce 100644
|
||||
index cdaf940..8b6ba77 100644
|
||||
--- a/src/operations_ccid.c
|
||||
+++ b/src/operations_ccid.c
|
||||
@@ -33,7 +33,7 @@
|
||||
@ -166,13 +167,13 @@ index 574155d..07834ce 100644
|
||||
}
|
||||
|
||||
diff --git a/src/operations_ccid.h b/src/operations_ccid.h
|
||||
index ec0070c..61cad72 100644
|
||||
index 20415c0..4d55ad8 100644
|
||||
--- a/src/operations_ccid.h
|
||||
+++ b/src/operations_ccid.h
|
||||
@@ -11,7 +11,10 @@ int authenticate_or_set_ccid(struct Device *dev, const char *admin_PIN);
|
||||
int set_secret_on_device_ccid(struct Device *dev, const char *admin_PIN, const char *OTP_secret_base32, const uint64_t hotp_counter);
|
||||
@@ -12,7 +12,10 @@ int set_secret_on_device_ccid(struct Device *dev, const char *admin_PIN, const c
|
||||
int verify_code_ccid(struct Device *dev, const uint32_t code_to_verify);
|
||||
int status_ccid(libusb_device_handle *handle, int *attempt_counter, uint16_t *firmware_version, uint32_t *serial_number);
|
||||
int status_ccid(libusb_device_handle *handle, struct FullResponseStatus *full_response);
|
||||
int nk3_change_pin(struct Device *dev, const char *old_pin, const char*new_pin);
|
||||
-int nk3_reset(struct Device *dev);
|
||||
+// new_pin can be `null`
|
||||
+//
|
||||
@ -182,17 +183,17 @@ index ec0070c..61cad72 100644
|
||||
|
||||
#endif//NITROKEY_HOTP_VERIFICATION_OPERATIONS_CCID_H
|
||||
|
||||
From 596f701985682adf6bfab06c78cbe132cbcb2aae Mon Sep 17 00:00:00 2001
|
||||
From 0bbc6ea354b1f807a4d7ad4c0cd57f9cbab25a8b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= <sosthene@nitrokey.com>
|
||||
Date: Tue, 3 Dec 2024 10:48:27 +0100
|
||||
Subject: [PATCH 3/3] Fix null pointer bug on non nk3
|
||||
Subject: [PATCH 3/4] Fix null pointer bug on non nk3
|
||||
|
||||
---
|
||||
src/operations_ccid.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/operations_ccid.c b/src/operations_ccid.c
|
||||
index 07834ce..538d434 100644
|
||||
index 8b6ba77..1221764 100644
|
||||
--- a/src/operations_ccid.c
|
||||
+++ b/src/operations_ccid.c
|
||||
@@ -36,6 +36,12 @@
|
||||
@ -217,3 +218,33 @@ index 07834ce..538d434 100644
|
||||
}
|
||||
|
||||
|
||||
|
||||
From 0c5bd3da36ea8de5b8adf7878e9260b079bc110b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= <sosthene@nitrokey.com>
|
||||
Date: Mon, 9 Dec 2024 17:42:54 +0100
|
||||
Subject: [PATCH 4/4] Print warning when device is not an NK3
|
||||
|
||||
---
|
||||
src/operations_ccid.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/operations_ccid.c b/src/operations_ccid.c
|
||||
index 1221764..356a1b4 100644
|
||||
--- a/src/operations_ccid.c
|
||||
+++ b/src/operations_ccid.c
|
||||
@@ -39,6 +39,7 @@ int nk3_reset(struct Device *dev, const char * new_pin) {
|
||||
|
||||
if (!dev->mp_devhandle_ccid) {
|
||||
// Not an NK3
|
||||
+ printf("No Nitrokey 3 found. No operation performed\n");
|
||||
return RET_NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -52,6 +53,7 @@ int nk3_reset(struct Device *dev, const char * new_pin) {
|
||||
|
||||
|
||||
if (usb_desc.idVendor != NITROKEY_USB_VID || usb_desc.idProduct != NITROKEY_3_USB_PID) {
|
||||
+ printf("No Nitrokey 3 found. No operation performed\n");
|
||||
return RET_NO_ERROR;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user