2019-08-15 18:36:05 +00:00
#!/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"
2022-11-09 16:51:27 +00:00
HEIGHT="0"
WIDTH="80"
2019-08-15 18:36:05 +00:00
USER_PIN_DEF=123456
ADMIN_PIN_DEF=12345678
TPM_PASS_DEF=12345678
2022-03-10 14:55:08 +00:00
USER_PIN=""
ADMIN_PIN=""
TPM_PASS=""
2022-06-02 17:52:51 +00:00
#Circumvent Librem Key/Nitrokey HOTP firmware bug https://github.com/osresearch/heads/issues/1167
MAX_HOTP_GPG_PIN_LENGTH=25
2022-03-10 14:55:08 +00:00
# What are the Security components affected by custom passwords
CUSTOM_PASS_AFFECTED_COMPONENTS=""
2020-12-10 15:32:48 +00:00
RSA_KEY_LENGTH=3072
2020-11-24 11:48:41 +00:00
2020-01-02 16:29:11 +00:00
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"
2020-10-23 23:38:30 +00:00
SKIP_BOOT="n"
2020-07-07 08:32:22 +00:00
2019-08-15 18:36:05 +00:00
## External files sourced
. /etc/functions
2022-04-06 21:25:40 +00:00
. /etc/luks-functions
2019-08-15 18:36:05 +00:00
. /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
2021-11-23 20:37:09 +00:00
whiptail $BG_COLOR_ERROR --msgbox "${msg}\n\n" $HEIGHT $WIDTH $BG_COLOR_ERROR --title "Error"
2019-08-15 18:36:05 +00:00
}
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
2020-08-05 09:49:06 +00:00
# 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}
2020-06-30 16:29:42 +00:00
fi
2020-11-24 11:48:41 +00:00
# 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
2019-08-15 18:36:05 +00:00
# Generate OEM GPG keys
{
echo admin
echo generate
echo n
echo ${ADMIN_PIN_DEF}
echo ${USER_PIN_DEF}
echo 0
echo y
2020-01-02 16:29:11 +00:00
echo ${GPG_USER_NAME}
echo ${GPG_USER_MAIL}
echo ${GPG_USER_COMMENT}
2019-08-15 18:36:05 +00:00
} | 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
}
2020-03-26 14:05:51 +00:00
2019-11-07 19:01:49 +00:00
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
2020-07-10 22:29:43 +00:00
ERROR=`cat /tmp/gpg_card_edit_output | fold -s`
2019-11-07 19:01:49 +00:00
whiptail_error_die "GPG Key PIN change failed!\n\n$ERROR"
fi
}
2019-08-15 18:36:05 +00:00
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
2022-04-13 18:24:59 +00:00
#Check if previous TPM Disk unlock Key was set
if [ -e /boot/kexec_key_devices.txt ]; then
TPM_DISK_ENCRYPTION_KEY_SET=1
fi
2019-08-15 18:36:05 +00:00
# clear any existing checksums/signatures
rm /boot/kexec* 2>/dev/null
# create Heads TPM counter
2020-04-23 23:36:03 +00:00
if [ "$CONFIG_TPM" = "y" ]; then
tpm counter_create \
2022-03-10 14:55:08 +00:00
-pwdo "$TPM_PASS" \
2020-04-23 23:36:03 +00:00
-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
2019-08-15 18:36:05 +00:00
2022-04-13 18:24:59 +00:00
# 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
2019-08-15 18:36:05 +00:00
# generate hashes
2022-12-31 17:41:24 +00:00
(
set -e -o pipefail
cd /boot
find ./ -type f ! -path './kexec*' -print0 \
| xargs -0 sha256sum > /boot/kexec_hashes.txt 2>/dev/null
print_tree > /boot/kexec_tree.txt
)
[ $? -eq 0 ] || whiptail_error_die "Error generating kexec hashes"
2019-08-15 18:36:05 +00:00
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 \
2022-03-10 14:55:08 +00:00
--passphrase "$USER_PIN" \
2019-08-15 18:36:05 +00:00
--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
2020-07-10 22:29:43 +00:00
ERROR=$(tail -n 1 /tmp/error | fold -s)
2019-08-15 18:36:05 +00:00
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
2020-07-29 03:24:32 +00:00
# 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
2020-07-29 03:26:20 +00:00
[ ! -s $option_file ] \
2019-08-15 18:36:05 +00:00
&& 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
2020-07-29 05:18:57 +00:00
# get correct index for entry
index=$(grep -n "$entry" $option_file | cut -f1 -d ':')
2019-08-15 18:36:05 +00:00
# write new config
2020-07-29 05:18:57 +00:00
echo "$entry" > /boot/kexec_default.$index.txt
2019-08-15 18:36:05 +00:00
# validate boot option
2020-07-13 22:22:40 +00:00
( cd /boot && /bin/kexec-boot -b "/boot" -e "$entry" -f \
| xargs sha256sum > $hash_file 2>/dev/null ) \
2019-08-15 18:36:05 +00:00
|| whiptail_error_die "Failed to create hashes of boot files"
}
2022-03-23 20:00:08 +00:00
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
2022-03-23 20:02:59 +00:00
date=`date "+%Y-%m-%d %H:%M:%S %Z"`
2022-03-23 20:00:08 +00:00
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
2022-11-15 20:11:58 +00:00
whiptail $CONFIG_WARNING_BG_COLOR --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." 0 80
2022-03-23 20:00:08 +00:00
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"
2023-01-11 18:59:26 +00:00
if ( cd /boot && sha256sum -c "$TMP_HASH_FILE" > /tmp/hash_output ); then
2022-03-23 20:00:08 +00:00
HASH="OK"
else
HASH="ALTERED"
fi
#Show results
2022-11-15 20:11:58 +00:00
whiptail $MAIN_MENU_BG_COLOR --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" 0 80
2022-03-23 20:00:08 +00:00
fi
}
2019-08-15 18:36:05 +00:00
## main script start
# check for args
if [ "$1" != "" ]; then
title_text=$1
else
2022-03-10 14:55:08 +00:00
title_text="OEM Factory Reset / Re-Ownership"
2019-08-15 18:36:05 +00:00
fi
if [ "$2" != "" ]; then
bg_color=$2
else
bg_color=""
fi
# show warning prompt
2020-04-23 23:36:03 +00:00
if [ "$CONFIG_TPM" = "y" ]; then
2022-03-10 14:55:08 +00:00
TPM_STR=" * ERASE the TPM and own it with a password\n"
2020-04-23 23:36:03 +00:00
else
TPM_STR=""
fi
2019-08-15 18:36:05 +00:00
if ! whiptail --yesno "
2022-03-10 14:55:08 +00:00
This operation will automatically:\n
2020-04-23 23:36:03 +00:00
$TPM_STR
* ERASE any keys or passwords on the GPG smart card,\n
2022-03-10 14:55:08 +00:00
reset it to a factory state, generate new keys\n
2022-04-29 20:58:34 +00:00
and optionally set custom PIN(s)\n
2020-04-23 23:36:03 +00:00
* 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
2022-03-10 14:55:08 +00:00
dedicated /boot partition. Do you wish to continue?" \
2021-10-29 17:35:16 +00:00
$HEIGHT $WIDTH $CONTINUE $CANCEL $CLEAR $bg_color --title "$title_text" ; then
2019-08-15 18:36:05 +00:00
exit 1
fi
2022-03-23 20:00:08 +00:00
# We show current integrity measurements status and time
report_integrity_measurements
2022-03-23 19:55:42 +00:00
# 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
2022-05-03 20:14:51 +00:00
luks_new_Disk_Recovery_Key_desired=1
2022-03-23 19:55:42 +00:00
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"
2022-03-10 14:55:08 +00:00
# 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"
2019-11-07 19:01:49 +00:00
# Prompt to change default passwords
2022-03-23 19:55:42 +00:00
echo -e -n "Would you like to set a single custom password that will be provisioned to previously stated security components? [y/N]: "
2019-11-07 19:01:49 +00:00
read -n 1 prompt_output
echo
if [ "$prompt_output" == "y" \
-o "$prompt_output" == "Y" ] \
; then
2022-06-02 17:52:51 +00:00
echo -e "\nThe chosen custom password must be between 8 and $MAX_HOTP_GPG_PIN_LENGTH characters in length.\n"
2019-11-20 22:27:40 +00:00
echo
2022-06-02 17:52:51 +00:00
while [[ ${#CUSTOM_SINGLE_PASS} -lt 8 ]] || [[ ${#CUSTOM_SINGLE_PASS} -gt $MAX_HOTP_GPG_PIN_LENGTH ]] ; do
2019-11-20 22:27:40 +00:00
echo -e -n "Enter the custom password: "
2022-03-10 14:55:08 +00:00
read CUSTOM_SINGLE_PASS
2019-11-20 22:27:40 +00:00
done
2019-11-07 19:01:49 +00:00
echo
2022-03-10 14:55:08 +00:00
TPM_PASS=$CUSTOM_SINGLE_PASS
USER_PIN=$CUSTOM_SINGLE_PASS
ADMIN_PIN=$CUSTOM_SINGLE_PASS
2022-03-23 19:55:42 +00:00
# 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
2022-03-10 14:55:08 +00:00
else
2022-03-23 19:55:42 +00:00
echo -e -n "Would you like to set distinct PINs/passwords to be provisioned to previously stated security components? [y/N]: "
2022-03-10 14:55:08 +00:00
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
2022-06-02 17:52:51 +00:00
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"
2022-03-10 14:55:08 +00:00
echo -e -n "Enter desired GPG Admin PIN: "
read ADMIN_PIN
done
2022-06-02 17:52:51 +00:00
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"
2022-03-10 14:55:08 +00:00
echo -e -n "Enter desired GPG User PIN: "
read USER_PIN
done
echo
fi
2019-11-07 19:01:49 +00:00
fi
2022-03-23 19:55:42 +00:00
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
2022-03-10 14:55:08 +00:00
# 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
2020-01-02 16:29:11 +00:00
# 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
2020-03-26 14:05:51 +00:00
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@address.org"
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@adress.org:"
read -r GPG_USER_MAIL
while ! $(expr "$GPG_USER_MAIL" : '.*@' >/dev/null); do
{
echo -e "\nEnter your email@address.org:"
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):"
2021-10-21 21:24:56 +00:00
read -r GPG_USER_COMMENT
while [[ ${#GPG_USER_COMMENT} -gt 60 ]]; do
2020-03-26 14:05:51 +00:00
{
echo -e "\nEnter Comment (Optional, to distinguish this key from others with same previous attributes. Must be smaller then 60 characters):"
2021-10-21 21:24:56 +00:00
read -r GPG_USER_COMMENT
2020-03-26 14:05:51 +00:00
};done
2020-01-02 16:29:11 +00:00
fi
2020-07-07 08:32:22 +00:00
## 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
2022-03-10 14:55:08 +00:00
# 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
2020-08-05 08:49:04 +00:00
ERROR=$(tail -n 1 /tmp/error | fold -s)
2020-07-07 08:32:22 +00:00
whiptail_error_die "Unable to mount USB on /media:\n\n${ERROR}"
2022-03-10 14:55:08 +00:00
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
2020-07-07 08:32:22 +00:00
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
2019-08-15 18:36:05 +00:00
2020-07-07 08:32:22 +00:00
# ensure USB Security Dongle connected
echo -e "\nChecking for USB Security Dongle...\n"
# USB kernel modules already loaded via mount-usb
2019-08-15 18:36:05 +00:00
if ! gpg --card-status >/dev/null 2>&1 ; then
2020-07-07 08:32:22 +00:00
whiptail_error "Can't access USB Security Dongle; \nPlease remove and reinsert, then press Enter."
2019-08-15 18:36:05 +00:00
if ! gpg --card-status >/dev/null 2>/tmp/error ; then
2020-07-10 22:29:43 +00:00
ERROR=$(tail -n 1 /tmp/error | fold -s)
2020-07-07 08:32:22 +00:00
whiptail_error_die "Unable to detect USB Security Dongle:\n\n${ERROR}"
2019-08-15 18:36:05 +00:00
fi
fi
2023-01-12 16:31:31 +00:00
assert_signable
2022-03-23 19:55:42 +00:00
# Action time...
2019-08-15 18:36:05 +00:00
# detect and set /boot device
echo -e "\nDetecting and setting boot device...\n"
if ! detect_boot_device ; then
2020-10-23 23:38:30 +00:00
SKIP_BOOT="y"
2019-08-15 18:36:05 +00:00
else
echo -e "Boot device set to $CONFIG_BOOT_DEV\n"
fi
# update configs
2020-10-23 23:38:30 +00:00
if [[ "$SKIP_BOOT" == "n" ]]; then
replace_config /etc/config.user "CONFIG_BOOT_DEV" "$CONFIG_BOOT_DEV"
combine_configs
fi
2019-08-15 18:36:05 +00:00
2022-03-23 19:55:42 +00:00
2022-05-03 20:14:51 +00:00
if [ -n "$luks_new_Disk_Recovery_Key_desired" -a -n "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then
2022-03-23 19:55:42 +00:00
#Reencryption of disk, disk recovery key and Disk Recovery Key passphrase change is requested
luks_reencrypt
luks_change_passphrase
2022-05-03 20:14:51 +00:00
elif [ -n "$luks_new_Disk_Recovery_Key_desired" -a -z "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then
2022-03-23 19:55:42 +00:00
#Reencryption of disk was requested but not passphrase change
luks_reencrypt
2022-05-03 20:14:51 +00:00
elif [ -z "$luks_new_Disk_Recovery_Key_desired" -a -n "$luks_new_Disk_Recovery_Key_passphrase_desired" ]; then
2022-03-23 19:55:42 +00:00
#Passphrase change is requested without disk reencryption
luks_change_passphrase
fi
2022-03-10 14:55:08 +00:00
## reset TPM and set password
2020-04-23 23:36:03 +00:00
if [ "$CONFIG_TPM" = "y" ]; then
echo -e "\nResetting TPM...\n"
{
2022-03-10 14:55:08 +00:00
echo $TPM_PASS
echo $TPM_PASS
2020-04-23 23:36:03 +00:00
} | /bin/tpm-reset >/dev/null 2>/tmp/error
if [ $? -ne 0 ]; then
2020-07-10 22:29:43 +00:00
ERROR=$(tail -n 1 /tmp/error | fold -s)
2020-04-23 23:36:03 +00:00
whiptail_error_die "Error resetting TPM:\n\n${ERROR}"
fi
2019-08-15 18:36:05 +00:00
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
2020-12-10 15:32:48 +00:00
echo -e "\nResetting GPG Key...\n(this will take around 3 minutes...)\n"
2019-08-15 18:36:05 +00:00
gpg_key_reset
2020-02-19 20:15:27 +00:00
# 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"
2022-03-10 14:55:08 +00:00
#Applying custom GPG PINs
if [ "$USER_PIN" != "" -o "$ADMIN_PIN" != "" ]; then
2019-11-07 19:01:49 +00:00
echo -e "\nChanging default GPG Admin PIN\n"
2022-03-10 14:55:08 +00:00
gpg_key_change_pin "3" "$ADMIN_PIN_DEF" "$ADMIN_PIN"
2019-11-07 19:01:49 +00:00
echo -e "\nChanging default GPG User PIN\n"
2022-03-10 14:55:08 +00:00
gpg_key_change_pin "1" "$USER_PIN_DEF" "$USER_PIN"
2019-11-07 19:01:49 +00:00
fi
2020-07-07 09:16:18 +00:00
# export pubkey to file
if ! gpg --export --armor $GPG_GEN_KEY > "${PUBKEY}" 2>/tmp/error ; then
2020-07-10 22:29:43 +00:00
ERROR=$(tail -n 1 /tmp/error | fold -s)
2020-07-07 09:16:18 +00:00
whiptail_error_die "GPG Key gpg export to file failed!\n\n$ERROR"
fi
## export pubkey to USB
2020-07-07 08:32:22 +00:00
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
2020-08-05 08:49:04 +00:00
ERROR=$(tail -n 1 /tmp/error | fold -s)
2020-07-07 08:32:22 +00:00
whiptail_error_die "Key export error: unable to copy ${GPG_GEN_KEY}.asc to /media:\n\n$ERROR"
fi
2022-03-10 14:55:08 +00:00
mount -o remount,ro /media 2>/dev/null
2019-08-15 18:36:05 +00:00
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
2020-07-10 22:29:43 +00:00
ERROR=$(tail -n 1 /tmp/error | fold -s)
2019-08-15 18:36:05 +00:00
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
2020-07-10 22:29:43 +00:00
ERROR=$(tail -n 1 /tmp/error | fold -s)
2019-08-15 18:36:05 +00:00
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
2020-07-10 22:29:43 +00:00
ERROR=$(tail -n 1 /tmp/error | fold -s)
2019-08-15 18:36:05 +00:00
whiptail_error_die "Error importing GPG ownertrust:\n\n$ERROR"
fi
if ! gpg --update-trust >/dev/null 2>/tmp/error ; then
2020-07-10 22:29:43 +00:00
ERROR=$(tail -n 1 /tmp/error | fold -s)
2019-08-15 18:36:05 +00:00
whiptail_error_die "Error updating GPG ownertrust:\n\n$ERROR"
fi
# clear any existing heads/gpg files from current firmware
2022-10-09 21:24:16 +00:00
for i in `cbfs.sh -o /tmp/oem-setup.rom -l | grep -e "heads/"`; do
cbfs.sh -o /tmp/oem-setup.rom -d $i
2019-08-15 18:36:05 +00:00
done
# add heads/gpg files to current firmware
if [ -e /.gnupg/pubring.kbx ];then
2022-10-09 21:24:16 +00:00
cbfs.sh -o /tmp/oem-setup.rom -a "heads/initrd/.gnupg/pubring.kbx" -f /.gnupg/pubring.kbx
2019-08-15 18:36:05 +00:00
if [ -e /.gnupg/pubring.gpg ];then
rm /.gnupg/pubring.gpg
fi
elif [ -e /.gnupg/pubring.gpg ];then
2022-10-09 21:24:16 +00:00
cbfs.sh -o /tmp/oem-setup.rom -a "heads/initrd/.gnupg/pubring.gpg" -f /.gnupg/pubring.gpg
2019-08-15 18:36:05 +00:00
fi
if [ -e /.gnupg/trustdb.gpg ]; then
2022-10-09 21:24:16 +00:00
cbfs.sh -o /tmp/oem-setup.rom -a "heads/initrd/.gnupg/trustdb.gpg" -f /.gnupg/trustdb.gpg
2019-08-15 18:36:05 +00:00
fi
# persist user config changes (boot device)
if [ -e /etc/config.user ]; then
2022-10-09 21:24:16 +00:00
cbfs.sh -o /tmp/oem-setup.rom -a "heads/initrd/etc/config.user" -f /etc/config.user
2019-08-15 18:36:05 +00:00
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
2020-07-10 22:29:43 +00:00
ERROR=$(tail -n 1 /tmp/error | fold -s)
2019-08-15 18:36:05 +00:00
whiptail_error_die "Error flashing updated firmware image:\n\n$ERROR"
fi
## sign files in /boot and generate checksums
2020-10-23 23:38:30 +00:00
if [[ "$SKIP_BOOT" == "n" ]]; then
echo -e "\nSigning boot files and generating checksums...\n"
generate_checksums
fi
2019-08-15 18:36:05 +00:00
2022-03-23 19:55:42 +00:00
# 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
2022-03-10 14:55:08 +00:00
whiptail --msgbox "
2022-03-23 19:55:42 +00:00
$luks_passphrase_changed
$tpm_password_changed
2022-03-10 14:55:08 +00:00
GPG Admin PIN: $ADMIN_PIN\n
GPG User PIN: $USER_PIN\n\n" \
$HEIGHT $WIDTH --title "Provisioned secrets"
2019-08-15 18:36:05 +00:00
## all done -- reboot
whiptail --msgbox "
2022-03-10 14:55:08 +00:00
OEM Factory Reset / Re-Ownership has completed successfully\n\n
2019-08-15 18:36:05 +00:00
After rebooting, you will need to generate new TOTP/HOTP secrets\n
when prompted in order to complete the setup process.\n\n
2019-11-26 17:10:39 +00:00
Press Enter to reboot.\n" \
2022-03-10 14:55:08 +00:00
$HEIGHT $WIDTH --title "OEM Factory Reset / Re-Ownership Complete"
2019-08-15 18:36:05 +00:00
2022-03-23 19:55:42 +00:00
# Clean LUKS secrets
luks_secrets_cleanup
unset luks_passphrase_changed
unset tpm_password_changed
2019-08-15 18:36:05 +00:00
reboot