-
-
Notifications
You must be signed in to change notification settings - Fork 187
/
seal-hotpkey
executable file
·180 lines (153 loc) · 6.1 KB
/
seal-hotpkey
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/bin/bash
# Retrieve the sealed TOTP secret and initialize a USB Security Dongle with it
. /etc/functions
. /etc/gui_functions
HOTP_SECRET="/tmp/secret/hotp.key"
HOTP_COUNTER="/boot/kexec_hotp_counter"
HOTP_KEY="/boot/kexec_hotp_key"
mount_boot()
{
TRACE_FUNC
# Mount local disk if it is not already mounted
if ! grep -q /boot /proc/mounts; then
if ! mount -o ro /boot; then
whiptail_error --title 'ERROR' \
--msgbox "Couldn't mount /boot.\n\nCheck the /boot device in configuration settings, or perform an OEM reset." 0 80
return 1
fi
fi
}
TRACE_FUNC
fatal_error()
{
echo -e "\nERROR: ${1}; press Enter to continue."
read
# get lsusb output for debugging
DEBUG "lsusb output: $(lsusb)"
die "$1"
}
# Use stored HOTP key branding (this might be useful after OEM reset)
if [ -r /boot/kexec_hotp_key ]; then
HOTPKEY_BRANDING="$(cat /boot/kexec_hotp_key)"
else
HOTPKEY_BRANDING="HOTP USB Security Dongle"
fi
if [ "$CONFIG_TPM" = "y" ]; then
DEBUG "Sealing HOTP secret reuses TOTP sealed secret..."
tpmr unseal 4d47 0,1,2,3,4,7 312 "$HOTP_SECRET" \
|| fatal_error "Unable to unseal HOTP secret"
else
# without a TPM, generate a secret based on the SHA-256 of the ROM
secret_from_rom_hash > "$HOTP_SECRET" || die "Reading ROM failed"
fi
# Store counter in file instead of TPM for now, as it conflicts with Heads
# config TPM counter as TPM 1.2 can only increment one counter between reboots
# get current value of HOTP counter in TPM, create if absent
mount_boot || exit 1
#check_tpm_counter $HOTP_COUNTER hotp \
#|| die "Unable to find/create TPM counter"
#counter="$TPM_COUNTER"
#
#counter_value=$(read_tpm_counter $counter | cut -f2 -d ' ' | awk 'gsub("^000e","")')
#if [ "$counter_value" == "" ]; then
# die "Unable to read HOTP counter"
#fi
#counter_value=$(printf "%d" 0x${counter_value})
counter_value=1
enable_usb
# While making sure the key is inserted, capture the status so we can check how
# many PIN attempts remain
if ! hotp_token_info="$(hotp_verification info)" ; then
echo -e "\nInsert your $HOTPKEY_BRANDING and press Enter to configure it"
read
if ! hotp_token_info="$(hotp_verification info)" ; then
# don't leak key on failure
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null
fatal_error "Unable to find $HOTPKEY_BRANDING"
fi
fi
# 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"
fi
# Truncate the secret if it is longer than the maximum HOTP secret
truncate_max_bytes 20 "$HOTP_SECRET"
# Check when the signing key was created to consider trying the default PIN
# (Note: we must avoid using gpg --card-status here as the Nitrokey firmware
# locks up, https://github.com/Nitrokey/nitrokey-pro-firmware/issues/54)
gpg_key_create_time="$(gpg --list-keys --with-colons | grep -m 1 '^pub:' | cut -d: -f6)"
gpg_key_create_time="${gpg_key_create_time:-0}"
DEBUG "Signature key was created at $(date -d "@$gpg_key_create_time")"
now_date="$(date '+%s')"
# Get the number of admin PIN retry attempts remaining
awk_admin_counter_regex='/^\s*Card counters: Admin (\d),.*$/'
awk_get_admin_counter="$awk_admin_counter_regex"' { print gensub('"$awk_admin_counter_regex"', "\\1", "") }'
admin_pin_retries="$(echo "$hotp_token_info" | awk "$awk_get_admin_counter")"
admin_pin_retries="${admin_pin_retries:-0}"
DEBUG "Admin PIN retry counter is $admin_pin_retries"
# 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
# so PIN attempts are not consumed by the default attempt.
admin_pin="12345678"
month_secs="$((30*24*60*60))"
admin_pin_status=1
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
echo "Not trying default PIN ($admin_pin)"
# Never consume an attempt if there are less than 3 attempts left, otherwise
# attempting the default PIN could cause an unexpected lockout before getting a
# chance to enter the correct PIN
elif [ "$admin_pin_retries" -lt 3 ]; then
echo "Not trying default PIN ($admin_pin), only $admin_pin_retries attempt(s) left"
else
hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" >/dev/null 2>&1
admin_pin_status="$?"
fi
if [ "$admin_pin_status" -ne 0 ]; then
# prompt user for PIN and retry
echo ""
read -s -p "Enter your $HOTPKEY_BRANDING Admin PIN: " admin_pin
echo -e "\n"
hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING"
if [ $? -ne 0 ]; then
echo -e "\n"
read -s -p "Error setting HOTP secret, re-enter Admin PIN and try again: " admin_pin
echo -e "\n"
if ! hotp_initialize "$admin_pin" $HOTP_SECRET $counter_value "$HOTPKEY_BRANDING" ; then
# don't leak key on failure
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null
if [ "$HOTPKEY_BRANDING" == "Nitrokey" ]; then
fatal_error "Setting HOTP secret failed, to reset nitrokey pin use: nitropy nk3 secrets reset or the Nitrokey App 2"
else
fatal_error "Setting HOTP secret failed"
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
# HOTP key no longer needed
shred -n 10 -z -u "$HOTP_SECRET" 2> /dev/null
# Make sure our counter is incremented ahead of the next check
#increment_tpm_counter $counter > /dev/null \
#|| die "Unable to increment tpm counter"
#increment_tpm_counter $counter > /dev/null \
#|| die "Unable to increment tpm counter"
mount -o remount,rw /boot
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
echo $HOTPKEY_BRANDING > $HOTP_KEY \
|| die "Unable to store hotp key file"
#sha256sum /tmp/counter-$counter > $HOTP_COUNTER \
#|| die "Unable to create hotp counter file"
mount -o remount,ro /boot
echo -e "\n$HOTPKEY_BRANDING initialized successfully. Press Enter to continue."
read
exit 0