-
-
Notifications
You must be signed in to change notification settings - Fork 189
/
Copy pathoem-factory-reset
executable file
·730 lines (647 loc) · 23.9 KB
/
oem-factory-reset
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
#!/bin/sh
# Automated setup of TPM, GPG keys, and disk
set -o pipefail
# use TERM to exit on error
trap "exit 1" TERM
export TOP_PID=$$
## Static local variables
CLEAR="--clear"
CONTINUE="--yes-button Continue"
CANCEL="--no-button Cancel"
HEIGHT="30"
WIDTH="90"
USER_PIN_DEF=123456
ADMIN_PIN_DEF=12345678
TPM_PASS_DEF=12345678
USER_PIN=""
ADMIN_PIN=""
TPM_PASS=""
#Circumvent Librem Key/Nitrokey HOTP firmware bug https://github.com/osresearch/heads/issues/1167
MAX_HOTP_GPG_PIN_LENGTH=25
# What are the Security components affected by custom passwords
CUSTOM_PASS_AFFECTED_COMPONENTS=""
RSA_KEY_LENGTH=3072
GPG_USER_NAME="OEM Key"
GPG_KEY_NAME=`date +%Y%m%d%H%M%S`
GPG_USER_MAIL="oem-${GPG_KEY_NAME}@example.com"
GPG_USER_COMMENT="OEM-generated key"
SKIP_BOOT="n"
## External files sourced
. /etc/functions
. /etc/luks-functions
. /tmp/config
## functions
die() {
local msg=$1
if [ -n "$msg" ]; then
echo -e "\n$msg"
fi
kill -s TERM $TOP_PID
exit 1
}
whiptail_error()
{
local msg=$1
if [ "$msg" = "" ]; then
die "whiptail error: An error msg is required"
fi
whiptail $BG_COLOR_ERROR --msgbox "${msg}\n\n" $HEIGHT $WIDTH $BG_COLOR_ERROR --title "Error"
}
whiptail_error_die()
{
whiptail_error "$@"
die
}
gpg_key_reset()
{
# Factory reset GPG card
{
echo admin
echo factory-reset
echo y
echo yes
} | gpg --command-fd=0 --status-fd=1 --pinentry-mode=loopback --card-edit \
> /tmp/gpg_card_edit_output 2>/dev/null
if [ $? -ne 0 ]; then
ERROR=`cat /tmp/gpg_card_edit_output`
whiptail_error_die "GPG Key factory reset failed!\n\n$ERROR"
fi
# If Nitrokey Storage is inserted, reset AES keys as well
if lsusb | grep -q "20a0:4109" && [ -x /bin/hotp_verification ] ; then
/bin/hotp_verification regenerate ${ADMIN_PIN_DEF}
fi
# Set RSA key length
{
echo admin
echo key-attr
echo 1 # RSA
echo ${RSA_KEY_LENGTH} #Signing key size set to RSA_KEY_LENGTH
echo ${ADMIN_PIN_DEF}
echo 1 # RSA
echo ${RSA_KEY_LENGTH} #Encryption key size set to RSA_KEY_LENGTH
echo ${ADMIN_PIN_DEF}
echo 1 # RSA
echo ${RSA_KEY_LENGTH} #Authentication key size set to RSA_KEY_LENGTH
echo ${ADMIN_PIN_DEF}
} | gpg --command-fd=0 --status-fd=1 --pinentry-mode=loopback --card-edit \
> /tmp/gpg_card_edit_output 2>/dev/null
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."
fi
# Generate OEM GPG keys
{
echo admin
echo generate
echo n
echo ${ADMIN_PIN_DEF}
echo ${USER_PIN_DEF}
echo 0
echo y
echo ${GPG_USER_NAME}
echo ${GPG_USER_MAIL}
echo ${GPG_USER_COMMENT}
} | gpg --command-fd=0 --status-fd=2 --pinentry-mode=loopback --card-edit \
> /tmp/gpg_card_edit_output 2>/dev/null
if [ $? -ne 0 ]; then
ERROR=`cat /tmp/gpg_card_edit_output`
whiptail_error_die "GPG Key automatic keygen failed!\n\n$ERROR"
fi
}
gpg_key_change_pin()
{
# 1 = user PIN, 3 = admin PIN
PIN_TYPE=$1
PIN_ORIG=$2
PIN_NEW=$3
# Change PIN
{
echo admin
echo passwd
echo ${PIN_TYPE}
echo ${PIN_ORIG}
echo ${PIN_NEW}
echo ${PIN_NEW}
echo q
echo q
} | gpg --command-fd=0 --status-fd=2 --pinentry-mode=loopback --card-edit \
> /tmp/gpg_card_edit_output 2>/dev/null
if [ $? -ne 0 ]; then
ERROR=`cat /tmp/gpg_card_edit_output | fold -s`
whiptail_error_die "GPG Key PIN change failed!\n\n$ERROR"
fi
}
generate_checksums()
{
# ensure /boot mounted
if ! grep -q /boot /proc/mounts ; then
mount -o rw /boot || whiptail_error_die "Unable to mount /boot"
else
mount -o remount,rw /boot || whiptail_error_die "Unable to mount /boot"
fi
#Check if previous TPM Disk unlock Key was set
if [ -e /boot/kexec_key_devices.txt ]; then
TPM_DISK_ENCRYPTION_KEY_SET=1
fi
# clear any existing checksums/signatures
rm /boot/kexec* 2>/dev/null
# create Heads TPM counter
if [ "$CONFIG_TPM" = "y" ]; then
tpm counter_create \
-pwdo "$TPM_PASS" \
-pwdc '' \
-la -3135106223 \
| tee /tmp/counter \
|| whiptail_error_die "Unable to create TPM counter"
TPM_COUNTER=`cut -d: -f1 < /tmp/counter`
# increment TPM counter
increment_tpm_counter $TPM_COUNTER >/dev/null 2>&1 \
|| whiptail_error_die "Unable to increment tpm counter"
# create rollback file
sha256sum /tmp/counter-$TPM_COUNTER > /boot/kexec_rollback.txt 2>/dev/null \
|| whiptail_error_die "Unable to create rollback file"
else
## needs to exist for initial call to unseal-hotp
echo "0" > /boot/kexec_hotp_counter
fi
# set default boot option only if no TPM Disk Unlock Key previously set
if [ -z "$TPM_DISK_ENCRYPTION_KEY_SET" ]; then
set_default_boot_option
fi
# generate hashes
find /boot -type f ! -name '*kexec*' -print0 \
| xargs -0 sha256sum > /boot/kexec_hashes.txt 2>/dev/null \
|| whiptail_error_die "Error generating kexec hashes"
param_files=`find /boot/kexec*.txt`
[ -z "$param_files" ] \
&& whiptail_error_die "No kexec parameter files to sign"
# sign kexec boot files
if sha256sum $param_files 2>/dev/null | gpg \
--pinentry-mode loopback \
--passphrase "$USER_PIN" \
--digest-algo SHA256 \
--detach-sign \
-a \
> /boot/kexec.sig 2>/tmp/error; then
# successful - update the validated params
if ! check_config /boot >/dev/null 2>/tmp/error ; then
cat /tmp/error
ret=1
else
ret=0
fi
else
cat /tmp/error
ret=1
fi
# done writing to /boot, switch back to RO
mount -o ro,remount /boot
if [ $ret = 1 ] ; then
ERROR=$(tail -n 1 /tmp/error | fold -s)
whiptail_error_die "Error signing kexec boot files:\n\n$ERROR"
fi
}
set_default_boot_option()
{
option_file="/tmp/kexec_options.txt"
tmp_menu_file="/tmp/kexec/kexec_menu.txt"
hash_file="/boot/kexec_default_hashes.txt"
mkdir -p /tmp/kexec/
rm $option_file 2>/dev/null
# parse boot options from grub.cfg
for i in `find /boot -name "grub.cfg"`; do
kexec-parse-boot "/boot" "$i" >> $option_file
done
# FC29/30+ may use BLS format grub config files
# https://fedoraproject.org/wiki/Changes/BootLoaderSpecByDefault
# only parse these if $option_file is still empty
if [ ! -s $option_file ] && [ -d "/boot/loader/entries" ]; then
for i in `find /boot -name "grub.cfg"`; do
kexec-parse-bls "/boot" "$i" "/boot/loader/entries" >> $option_file
done
fi
[ ! -s $option_file ] \
&& whiptail_error_die "Failed to parse any boot options"
# sort boot options
sort -r $option_file | uniq > $tmp_menu_file
## save first option as default
entry=`head -n 1 $tmp_menu_file | tail -1`
# clear existing default configs
rm "/boot/kexec_default.*.txt" 2>/dev/null
# get correct index for entry
index=$(grep -n "$entry" $option_file | cut -f1 -d ':')
# write new config
echo "$entry" > /boot/kexec_default.$index.txt
# validate boot option
( cd /boot && /bin/kexec-boot -b "/boot" -e "$entry" -f \
| xargs sha256sum > $hash_file 2>/dev/null ) \
|| whiptail_error_die "Failed to create hashes of boot files"
}
report_integrity_measurements()
{
#check for GPG key in keyring
GPG_KEY_COUNT=`gpg -k 2>/dev/null | wc -l`
if [ $GPG_KEY_COUNT -ne 0 ]; then
# Check and report TOTP
# update the TOTP code every thirty seconds
date=`date "+%Y-%m-%d %H:%M:%S %Z"`
seconds=`date "+%s"`
half=`expr \( $seconds % 60 \) / 30`
if [ "$CONFIG_TPM" = n ]; then
TOTP="NO TPM"
elif [ "$half" != "$last_half" ]; then
last_half=$half;
TOTP=`unseal-totp` > /dev/null 2>&1
fi
# Check and report on HOTP status
if [ -x /bin/hotp_verification ]; then
HOTP=`unseal-hotp` > /dev/null 2>&1
enable_usb
if ! hotp_verification info > /dev/null 2>&1 ; then
whiptail $CONFIG_WARNING_BG_COLOR --clear --title 'WARNING: Please insert your HOTP enabled USB Security dongle' --msgbox "Your HOTP enabled USB Security dongle was not detected.\n\nPlease remove it and insert it again." 30 90
fi
# Don't output HOTP codes to screen, so as to make replay attacks harder
hotp_verification check $HOTP
case "$?" in
0 )
HOTP="Success"
;;
4 )
HOTP="Invalid code"
MAIN_MENU_BG_COLOR=$CONFIG_ERROR_BG_COLOR
;;
* )
HOTP="Error checking code, Insert USB Security dongle and retry"
MAIN_MENU_BG_COLOR=$CONFIG_WARNING_BG_COLOR
;;
esac
else
HOTP='N/A'
fi
# Check for detached signed digest and report on /boot integrity status
check_config /boot force
TMP_HASH_FILE="/tmp/kexec/kexec_hashes.txt"
if cd /boot && sha256sum -c "$TMP_HASH_FILE" > /tmp/hash_output ; then
HASH="OK"
cd /
else
HASH="ALTERED"
fi
#Show results
whiptail $MAIN_MENU_BG_COLOR --clear --title "Measured Integrity Report" --msgbox "$date\nTOTP: $TOTP | HOTP: $HOTP\n/BOOT INTEGRITY: $HASH\n\nPress OK to continue or Ctrl+Alt+Delete to reboot" 30 90
fi
}
## main script start
# check for args
if [ "$1" != "" ]; then
title_text=$1
else
title_text="OEM Factory Reset / Re-Ownership"
fi
if [ "$2" != "" ]; then
bg_color=$2
else
bg_color=""
fi
# show warning prompt
if [ "$CONFIG_TPM" = "y" ]; then
TPM_STR=" * ERASE the TPM and own it with a password\n"
else
TPM_STR=""
fi
if ! whiptail --yesno "
This operation will automatically:\n
$TPM_STR
* ERASE any keys or passwords on the GPG smart card,\n
reset it to a factory state, generate new keys\n
and optionally set custom PIN(s)
* Add the new GPG key to the firmware and reflash it\n
* Sign all of the files in /boot with the new GPG key\n\n
It requires that you already have an OS installed on a\n
dedicated /boot partition. Do you wish to continue?" \
$HEIGHT $WIDTH $CONTINUE $CANCEL $CLEAR $bg_color --title "$title_text" ; then
exit 1
fi
# We show current integrity measurements status and time
report_integrity_measurements
# Re-ownership of encrypted disk key, content and passphrase
echo -e -n "Would you like to change the current LUKS Disk Recovery Key passphrase?\n (Highly recommended if you didn't install the Operating System yourself, so that past provisioned passphrase would not permit to access content.\n Note that without re-encrypting disk, a backuped header could be restored to access encrypted content with old passphrase) [y/N]: "
read -n 1 prompt_output
echo
if [ "$prompt_output" == "y" \
-o "$prompt_output" == "Y" ];then
luks_new_Disk_Recovery_Key_passphrase_desired=1
echo -e "\n"
fi
echo -e -n "Would you like to re-encrypt LUKS encrypted container and generate new Disk Recovery key?\n (Highly recommended if you didn't install the operating system yourself: this would prevent any LUKS backuped header to be restored to access encrypted data) [y/N]: "
read -n 1 prompt_output
echo
if [ "$prompt_output" == "y" \
-o "$prompt_output" == "Y" ];then
test_luks_current_disk_recovery_key_passphrase
luks_new_Disk_Recovery_Key_desired=1
echo -e "\n"
fi
# Adapt message to be given to user in terms of security components that will be applied.
if [ -n "$luks_new_Disk_Recovery_Key_passphrase_desired" -o -n "$luks_new_Disk_Recovery_Key_passphrase" ]; then
CUSTOM_PASS_AFFECTED_COMPONENTS="LUKS Disk Recovery Key passphrase"
fi
if [ "$CONFIG_TPM" = "y" ]; then
CUSTOM_PASS_AFFECTED_COMPONENTS="$CUSTOM_PASS_AFFECTED_COMPONENTS
TPM Ownership password"
fi
CUSTOM_PASS_AFFECTED_COMPONENTS="$CUSTOM_PASS_AFFECTED_COMPONENTS
GPG Admin PIN
GPG User PIN"
# Inform user of security components affected for the following prompts
echo -e "The following security components will be provisioned with defaults or chosen PINs/passwords:
$CUSTOM_PASS_AFFECTED_COMPONENTS\n"
# Prompt to change default passwords
echo -e -n "Would you like to set a single custom password that will be provisioned to previously stated security components? [y/N]: "
read -n 1 prompt_output
echo
if [ "$prompt_output" == "y" \
-o "$prompt_output" == "Y" ] \
; then
echo -e "\nThe chosen custom password must be between 8 and $MAX_HOTP_GPG_PIN_LENGTH characters in length.\n"
echo
while [[ ${#CUSTOM_SINGLE_PASS} -lt 8 ]] || [[ ${#CUSTOM_SINGLE_PASS} -gt $MAX_HOTP_GPG_PIN_LENGTH ]] ; do
echo -e -n "Enter the custom password: "
read CUSTOM_SINGLE_PASS
done
echo
TPM_PASS=$CUSTOM_SINGLE_PASS
USER_PIN=$CUSTOM_SINGLE_PASS
ADMIN_PIN=$CUSTOM_SINGLE_PASS
# Only set if user said desired. Matches rest of logic
if [ -n "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then
luks_new_Disk_Recovery_Key_passphrase=$CUSTOM_SINGLE_PASS
fi
else
echo -e -n "Would you like to set distinct PINs/passwords to be provisioned to previously stated security components? [y/N]: "
read -n 1 prompt_output
echo
if [ "$prompt_output" == "y" \
-o "$prompt_output" == "Y" ] \
; then
echo -e "\nThey must be each at least 8 characters in length.\n"
echo
if [ "$CONFIG_TPM" = "y" ]; then
while [[ ${#TPM_PASS} -lt 8 ]] ; do
echo -e -n "Enter desired TPM Ownership password: "
read TPM_PASS
done
fi
while [[ ${#ADMIN_PIN} -lt 8 ]] || [[ ${#ADMIN_PIN} -gt $MAX_HOTP_GPG_PIN_LENGTH ]] ; do
echo -e -n "\nThis PIN should be between 8 to $MAX_HOTP_GPG_PIN_LENGTH characters in length.\n"
echo -e -n "Enter desired GPG Admin PIN: "
read ADMIN_PIN
done
while [[ ${#USER_PIN} -lt 8 ]] || [[ ${#USER_PIN} -gt 64 ]]; do
echo -e -n "\nThis PIN should be between 8 to 64 characters in length.\n"
echo -e -n "Enter desired GPG User PIN: "
read USER_PIN
done
echo
fi
fi
if [ -n "$luks_new_Disk_Recovery_Key_passphrase_desired" -a -z "$luks_new_Disk_Recovery_Key_passphrase" ]; then
# We catch here if changing LUKS Disk Recovery Key passphrase was desired
# but yet undone. This is if not being covered by the single password
echo -e "\nEnter desired replacement for current Disk Recovery Key passphrase (At least 8 characters long):"
while [[ ${#luks_new_Disk_Recovery_Key_passphrase} -lt 8 ]]; do
{
read -r luks_new_Disk_Recovery_Key_passphrase
};done
#We test that current Disk Recovery Key passphrase is known prior of going further
test_luks_current_disk_recovery_key_passphrase
echo -e "\n"
fi
# If nothing is stored in custom variables, we set them to their defaults
if [ "$TPM_PASS" == "" ]; then TPM_PASS=$TPM_PASS_DEF; fi
if [ "$USER_PIN" == "" ]; then USER_PIN=$USER_PIN_DEF; fi
if [ "$ADMIN_PIN" == "" ]; then ADMIN_PIN=$ADMIN_PIN_DEF; fi
# Prompt to change default GnuPG key information
echo -e -n "Would you like to set custom user information for the GnuPG key? [y/N]: "
read -n 1 prompt_output
echo
if [ "$prompt_output" == "y" \
-o "$prompt_output" == "Y" ] \
; then
echo -e "\n\n"
echo -e "We will generate a GnuPG (PGP) keypair identifiable with the following text form:"
echo -e "Real Name (Comment) [email protected]"
echo -e "\nEnter your Real Name (At least 5 characters long):"
read -r GPG_USER_NAME
while [[ ${#GPG_USER_NAME} -lt 5 ]]; do
{
echo -e "\nEnter your Real Name (At least 5 characters long):"
read -r GPG_USER_NAME
};done
echo -e "\nEnter your [email protected]:"
read -r GPG_USER_MAIL
while ! $(expr "$GPG_USER_MAIL" : '.*@' >/dev/null); do
{
echo -e "\nEnter your [email protected]:"
read -r GPG_USER_MAIL
};done
echo -e "\nEnter Comment (Optional, to distinguish this key from others with same previous attributes. Must be smaller then 60 characters):"
read -r GPG_USER_COMMENT
while [[ ${#GPG_USER_COMMENT} -gt 60 ]]; do
{
echo -e "\nEnter Comment (Optional, to distinguish this key from others with same previous attributes. Must be smaller then 60 characters):"
read -r GPG_USER_COMMENT
};done
fi
## sanity check the USB, GPG key, and boot device before proceeding further
# Prompt to insert USB drive if desired
echo -e -n "Would you like to export your public key to an USB drive? [y/N]: "
read -n 1 prompt_output
echo
if [ "$prompt_output" == "y" \
-o "$prompt_output" == "Y" ] \
; then
GPG_EXPORT=1
# mount USB over /media only if not already mounted
if ! grep -q /media /proc/mounts ; then
# mount USB in rw
if ! mount-usb rw 2>/tmp/error; then
ERROR=$(tail -n 1 /tmp/error | fold -s)
whiptail_error_die "Unable to mount USB on /media:\n\n${ERROR}"
fi
else
#/media already mounted, make sure it is in r+w mode
if ! mount -o remount,rw /media 2>/tmp/error; then
ERROR=$(tail -n 1 /tmp/error | fold -s)
whiptail_error_die "Unable to remount in read+write USB on /media:\n\n${ERROR}"
fi
fi
else
GPG_EXPORT=0
# needed for USB Security dongle below and is ensured via mount-usb in case of GPG_EXPORT=1
enable_usb
fi
# ensure USB Security Dongle connected
echo -e "\nChecking for USB Security Dongle...\n"
# USB kernel modules already loaded via mount-usb
if ! gpg --card-status >/dev/null 2>&1 ; then
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}"
fi
fi
# Action time...
# detect and set /boot device
echo -e "\nDetecting and setting boot device...\n"
if ! detect_boot_device ; then
SKIP_BOOT="y"
else
echo -e "Boot device set to $CONFIG_BOOT_DEV\n"
fi
# update configs
if [[ "$SKIP_BOOT" == "n" ]]; then
replace_config /etc/config.user "CONFIG_BOOT_DEV" "$CONFIG_BOOT_DEV"
combine_configs
fi
if [ -n "$luks_new_Disk_Recovery_Key_desired" -a -n "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then
#Reencryption of disk, disk recovery key and Disk Recovery Key passphrase change is requested
luks_reencrypt
luks_change_passphrase
elif [ -n "$luks_new_Disk_Recovery_Key_desired" -a -z "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then
#Reencryption of disk was requested but not passphrase change
luks_reencrypt
elif [ -z "$luks_new_Disk_Recovery_Key_desired" -a -n "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then
#Passphrase change is requested without disk reencryption
luks_change_passphrase
fi
## reset TPM and set password
if [ "$CONFIG_TPM" = "y" ]; then
echo -e "\nResetting TPM...\n"
{
echo $TPM_PASS
echo $TPM_PASS
} | /bin/tpm-reset >/dev/null 2>/tmp/error
if [ $? -ne 0 ]; then
ERROR=$(tail -n 1 /tmp/error | fold -s)
whiptail_error_die "Error resetting TPM:\n\n${ERROR}"
fi
fi
# clear local keyring
rm /.gnupg/*.gpg 2>/dev/null
rm /.gnupg/*.kbx 2>/dev/null
gpg --list-keys >/dev/null 2>&1
## reset the GPG Key
echo -e "\nResetting GPG Key...\n(this will take around 3 minutes...)\n"
gpg_key_reset
# parse name of generated key
GPG_GEN_KEY=`grep -A1 pub /tmp/gpg_card_edit_output | tail -n1 | sed -nr 's/^([ ])*//p'`
PUBKEY="/tmp/${GPG_GEN_KEY}.asc"
#Applying custom GPG PINs
if [ "$USER_PIN" != "" -o "$ADMIN_PIN" != "" ]; then
echo -e "\nChanging default GPG Admin PIN\n"
gpg_key_change_pin "3" "$ADMIN_PIN_DEF" "$ADMIN_PIN"
echo -e "\nChanging default GPG User PIN\n"
gpg_key_change_pin "1" "$USER_PIN_DEF" "$USER_PIN"
fi
# export pubkey to file
if ! gpg --export --armor $GPG_GEN_KEY > "${PUBKEY}" 2>/tmp/error ; then
ERROR=$(tail -n 1 /tmp/error | fold -s)
whiptail_error_die "GPG Key gpg export to file failed!\n\n$ERROR"
fi
## export pubkey to USB
if [ $GPG_EXPORT -ne 0 ]; then
echo -e "\nExporting generated key to USB...\n"
# copy to USB
if ! cp "${PUBKEY}" "/media/${GPG_GEN_KEY}.asc" 2>/tmp/error ; then
ERROR=$(tail -n 1 /tmp/error | fold -s)
whiptail_error_die "Key export error: unable to copy ${GPG_GEN_KEY}.asc to /media:\n\n$ERROR"
fi
mount -o remount,ro /media 2>/dev/null
fi
## flash generated key to ROM
echo -e "\nReading current firmware...\n(this will take a minute or two)\n"
/bin/flash.sh -r /tmp/oem-setup.rom >/dev/null 2>/tmp/error
if [ ! -s /tmp/oem-setup.rom ]; then
ERROR=$(tail -n 1 /tmp/error | fold -s)
whiptail_error_die "Error reading current firmware:\n\n$ERROR"
fi
# ensure key imported locally
if ! cat "$PUBKEY" | gpg --import >/dev/null 2>/tmp/error ; then
ERROR=$(tail -n 1 /tmp/error | fold -s)
whiptail_error_die "Error importing GPG key:\n\n$ERROR"
fi
# update /.gnupg/trustdb.gpg to ultimately trust all user provided public keys
if ! gpg --list-keys --fingerprint --with-colons 2>/dev/null \
| sed -E -n -e 's/^fpr:::::::::([0-9A-F]+):$/\1:6:/p' \
| gpg --import-ownertrust >/dev/null 2>/tmp/error ; then
ERROR=$(tail -n 1 /tmp/error | fold -s)
whiptail_error_die "Error importing GPG ownertrust:\n\n$ERROR"
fi
if ! gpg --update-trust >/dev/null 2>/tmp/error ; then
ERROR=$(tail -n 1 /tmp/error | fold -s)
whiptail_error_die "Error updating GPG ownertrust:\n\n$ERROR"
fi
# clear any existing heads/gpg files from current firmware
for i in `cbfs -o /tmp/oem-setup.rom -l | grep -e "heads/"`; do
cbfs -o /tmp/oem-setup.rom -d $i
done
# add heads/gpg files to current firmware
if [ -e /.gnupg/pubring.kbx ];then
cbfs -o /tmp/oem-setup.rom -a "heads/initrd/.gnupg/pubring.kbx" -f /.gnupg/pubring.kbx
if [ -e /.gnupg/pubring.gpg ];then
rm /.gnupg/pubring.gpg
fi
elif [ -e /.gnupg/pubring.gpg ];then
cbfs -o /tmp/oem-setup.rom -a "heads/initrd/.gnupg/pubring.gpg" -f /.gnupg/pubring.gpg
fi
if [ -e /.gnupg/trustdb.gpg ]; then
cbfs -o /tmp/oem-setup.rom -a "heads/initrd/.gnupg/trustdb.gpg" -f /.gnupg/trustdb.gpg
fi
# persist user config changes (boot device)
if [ -e /etc/config.user ]; then
cbfs -o /tmp/oem-setup.rom -a "heads/initrd/etc/config.user" -f /etc/config.user
fi
# flash updated firmware image
echo -e "\nAdding generated key to current firmware and re-flashing...\n"
if ! /bin/flash.sh /tmp/oem-setup.rom >/dev/null 2>/tmp/error ; then
ERROR=$(tail -n 1 /tmp/error | fold -s)
whiptail_error_die "Error flashing updated firmware image:\n\n$ERROR"
fi
## sign files in /boot and generate checksums
if [[ "$SKIP_BOOT" == "n" ]]; then
echo -e "\nSigning boot files and generating checksums...\n"
generate_checksums
fi
# Prepare whiptail output of provisioned secrets
if [ -z "$luks_new_Disk_Recovery_Key_passphrase" -o -z "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then
luks_passphrase_changed=""
else
luks_passphrase_changed="LUKS Disk Recovery Key passphrase:\n
$luks_new_Disk_Recovery_Key_passphrase"
fi
if [ "$CONFIG_TPM" = "y" ]; then
tpm_password_changed="
TPM Owner Password: $TPM_PASS\n"
else
tpm_password_changed=""
fi
## Show to user current provisioned secrets prior of rebooting
whiptail --msgbox "
$luks_passphrase_changed
$tpm_password_changed
GPG Admin PIN: $ADMIN_PIN\n
GPG User PIN: $USER_PIN\n\n" \
$HEIGHT $WIDTH --title "Provisioned secrets"
## all done -- reboot
whiptail --msgbox "
OEM Factory Reset / Re-Ownership has completed successfully\n\n
After rebooting, you will need to generate new TOTP/HOTP secrets\n
when prompted in order to complete the setup process.\n\n
Press Enter to reboot.\n" \
$HEIGHT $WIDTH --title "OEM Factory Reset / Re-Ownership Complete"
# Clean LUKS secrets
luks_secrets_cleanup
unset luks_passphrase_changed
unset tpm_password_changed
reboot