+# Check for evidence that we're running in Secure Boot mode. If so, and if
+# appropriate options haven't been set, warn the user and offer to abort.
+# If we're NOT in Secure Boot mode but the user HAS specified the --shim
+# or --localkeys option, warn the user and offer to abort.
+#
+# FIXME: Although I checked the presence (and lack thereof) of the
+# /sys/firmware/efi/vars/SecureBoot* files on my Secure Boot test system
+# before releasing this script, I've since found that they are at least
+# sometimes present when Secure Boot is absent. This means that the first
+# test can produce false alarms. A better test is highly desirable.
+CheckSecureBoot() {
+ VarFile=`ls -d /sys/firmware/efi/vars/SecureBoot* 2> /dev/null`
+ if [[ -n $VarFile && $TargetDir != '/EFI/BOOT' && $ShimSource == "none" ]] ; then
+ echo ""
+ echo "CAUTION: Your computer appears to support Secure Boot, but you haven't"
+ echo "specified a valid shim.efi file source. If you've disabled Secure Boot and"
+ echo "intend to leave it disabled, this is fine; but if Secure Boot is active, the"
+ echo "resulting installation won't boot. You can read more about this topic at"
+ echo "http://www.rodsbooks.com/refind/secureboot.html."
+ echo ""
+ echo -n "Do you want to proceed with installation (Y/N)? "
+ ReadYesNo
+ if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
+ echo "OK; continuing with the installation..."
+ else
+ exit 0
+ fi
+ fi
+
+ if [[ $ShimSource != "none" && ! -n $VarFile ]] ; then
+ echo ""
+ echo "You've specified installing using a shim.efi file, but your computer does not"
+ echo "appear to be running in Secure Boot mode. Although installing in this way"
+ echo "should work, it's unnecessarily complex. You may continue, but unless you"
+ echo "plan to enable Secure Boot, you should consider stopping and omitting the"
+ echo "--shim option. You can read more about this topic at"
+ echo "http://www.rodsbooks.com/refind/secureboot.html."
+ echo ""
+ echo -n "Do you want to proceed with installation (Y/N)? "
+ ReadYesNo
+ if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
+ echo "OK; continuing with the installation..."
+ else
+ exit 0
+ fi
+ fi
+
+ if [[ $LocalKeys != 0 && ! -n $VarFile ]] ; then
+ echo ""
+ echo "You've specified re-signing your rEFInd binaries with locally-generated keys,"
+ echo "but your computer does not appear to be running in Secure Boot mode. The"
+ echo "keys you generate will be useless unless you enable Secure Boot. You may"
+ echo "proceed with this installation, but before you do so, you may want to read"
+ echo "more about it at http://www.rodsbooks.com/refind/secureboot.html."
+ echo ""
+ echo -n "Do you want to proceed with installation (Y/N)? "
+ ReadYesNo
+ if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
+ echo "OK; continuing with the installation..."
+ else
+ exit 0
+ fi
+ fi
+
+} # CheckSecureBoot()
+
+# Check for the presence of locally-generated keys from a previous installation in
+# $EtcKeysDir (/etc/refind.d/keys). If they're not present, generate them using
+# openssl.
+GenerateKeys() {
+ PrivateKey=$EtcKeysDir/$LocalKeysBase.key
+ CertKey=$EtcKeysDir/$LocalKeysBase.crt
+ DerKey=$EtcKeysDir/$LocalKeysBase.cer
+ OpenSSL=`which openssl 2> /dev/null`
+
+ # Do the work only if one or more of the necessary keys is missing
+ # TODO: Technically, we don't need the DerKey; but if it's missing and openssl
+ # is also missing, this will fail. This could be improved.
+ if [[ ! -f $PrivateKey || ! -f $CertKey || ! -f $DerKey ]] ; then
+ echo "Generating a fresh set of local keys...."
+ mkdir -p $EtcKeysDir
+ chmod 0700 $EtcKeysDir
+ if [[ ! -x $OpenSSL ]] ; then
+ echo "Can't find openssl, which is required to create your private signing keys!"
+ echo "Aborting!"
+ exit 1
+ fi
+ if [[ -f $PrivateKey ]] ; then
+ echo "Backing up existing $PrivateKey"
+ cp -f $PrivateKey $PrivateKey.backup 2> /dev/null
+ fi
+ if [[ -f $CertKey ]] ; then
+ echo "Backing up existing $CertKey"
+ cp -f $CertKey $CertKey.backup 2> /dev/null
+ fi
+ if [[ -f $DerKey ]] ; then
+ echo "Backing up existing $DerKey"
+ cp -f $DerKey $DerKey.backup 2> /dev/null
+ fi
+ $OpenSSL req -new -x509 -newkey rsa:2048 -keyout $PrivateKey -out $CertKey \
+ -nodes -days 3650 -subj "/CN=Locally-generated rEFInd key/"
+ $OpenSSL x509 -in $CertKey -out $DerKey -outform DER
+ chmod 0600 $PrivateKey
+ else
+ echo "Using existing local keys...."
+ fi
+}
+
+# Sign a single binary. Requires parameters:
+# $1 = source file
+# $2 = destination file
+# Also assumes that the SBSign, PESign, UseSBSign, UsePESign, and various key variables are set
+# appropriately.
+# Aborts script on error
+SignOneBinary() {
+ $SBSign --key $PrivateKey --cert $CertKey --output $2 $1
+ if [[ $? != 0 ]] ; then
+ echo "Problem signing the binary $1! Aborting!"
+ exit 1
+ fi
+}
+
+# Re-sign the x86-64 binaries with a locally-generated key, First look for appropriate
+# key files in $EtcKeysDir. If they're present, use them to re-sign the binaries. If
+# not, try to generate new keys and store them in $EtcKeysDir.
+ReSignBinaries() {
+ SBSign=`which sbsign 2> /dev/null`
+ echo "Found sbsign at $SBSign"
+ TempDir="/tmp/refind_local"
+ if [[ ! -x $SBSign ]] ; then
+ echo "Can't find sbsign, which is required to sign rEFInd with your own keys!"
+ echo "Aborting!"
+ exit 1
+ fi
+ GenerateKeys
+ mkdir -p $TempDir/drivers_x64
+ cp $RefindDir/refind.conf-sample $TempDir 2> /dev/null
+ cp $ThisDir/refind.conf-sample $TempDir 2> /dev/null
+ cp $RefindDir/refind_ia32.efi $TempDir 2> /dev/null
+ cp -a $RefindDir/drivers_ia32 $TempDir 2> /dev/null
+ cp -a $ThisDir/drivers_ia32 $TempDir 2> /dev/null
+ SignOneBinary $RefindDir/refind_x64.efi $TempDir/refind_x64.efi
+ for Driver in `ls $RefindDir/drivers_x64/*.efi $ThisDir/drivers_x64/*.efi 2> /dev/null` ; do
+ TempName=`basename $Driver`
+ SignOneBinary $Driver $TempDir/drivers_x64/$TempName
+ done
+ RefindDir=$TempDir
+ DeleteRefindDir=1
+}
+
+# Identifies the ESP's location (/boot or /boot/efi, or these locations under
+# the directory specified by --root); aborts if the ESP isn't mounted at
+# either location.
+# Sets InstallDir to the ESP mount point.