+# 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"
+ SaveIFS=$IFS
+ IFS=$(echo -en "\n\b")
+ 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
+ IFS=$SaveIFS
+ RefindDir="$TempDir"
+ DeleteRefindDir=1
+} # ReSignBinaries()
+
+# Locate and mount an ESP, if possible, based on parted output.
+# Should be called only if /boot/efi is NOT an acceptable ESP.
+# Sets InstallDir to the mounted ESP's path ($RootDir/boot/efi)
+# and EspFilesystem the filesystem (always "vfat")