Add complete guide and all config variants
This commit is contained in:
107
hackintosh-guide/Utilities/ShimUtils/README.md
Executable file
107
hackintosh-guide/Utilities/ShimUtils/README.md
Executable file
@@ -0,0 +1,107 @@
|
||||
## OpenCore + OpenLinuxBoot + Secure Boot
|
||||
|
||||
If you want to use OpenCore + OpenLinuxBoot + Secure Boot it is possible to sign everything
|
||||
manually yourself, including any new Linux kernels after updates. This is possible since most
|
||||
standard distros leave at least the previous kernel bootable (and OpenLinuxBoot exposes
|
||||
this, via the Auxiliary menu), so you can boot into the old kernel, then sign the new
|
||||
kernel yourself.
|
||||
|
||||
More convenient may be to trust the signing keys of the specific distros which you
|
||||
want to boot, which are bundled into the `shimx64.efi` file installed with each distro.
|
||||
You can extract these with `shim-to-cert.tool` distributed with OpenCore, then install
|
||||
them in your system Secure Boot `db` variable. Best practice would be to install the deny
|
||||
list (`vendor.dbx`) from `shimx64.efi`, if any, into your system `dbx` variable, as well.
|
||||
(Otherwise you are ignoring any revocations which the vendor has made.)
|
||||
|
||||
Recently, Shim has added SBAT support, as a more efficient way to revoke unsafe
|
||||
binaries. Unfortunately, the SBAT enforcement code is part of Shim, and is not
|
||||
something you can extract and add to your system Secure Boot database.
|
||||
|
||||
To work round this, the new recommended way to boot OpenCore + OpenLinuxBoot +
|
||||
Secure Boot is to make a user build of Shim. The vendor certificates
|
||||
and revocation lists extracted from the distro `shimx64.efi` files are combined
|
||||
and signed by you, into your own build of Shim; in this approach, these vendor
|
||||
certificates should NOT also be included in the system Secure Boot database,
|
||||
and should be removed if you added them previously. Including them in both places
|
||||
will still boot under Secure Boot, but will effectively disable SBAT revocation.
|
||||
|
||||
> If you are signing everything yourself, including Linux kernels after updates, that
|
||||
will still work as before and the below is not needed. Equally, if you are not
|
||||
using Secure Boot the below is not needed.
|
||||
|
||||
The advantages of using a user build of Shim are:
|
||||
- No need to sign every kernel after updates (same as previous method)
|
||||
- Linux SBAT integration (new)
|
||||
- Linux MOK integration (new)
|
||||
- No need to include the Windows intermediate CA - you are trusting whichever distro
|
||||
keys you choose to include in your own Shim, directly (new)
|
||||
|
||||
Disadvantages are:
|
||||
- Need to update when distro keys or distro revocation lists within Shim are updated
|
||||
(same as previous method)
|
||||
- Need to udpate when Shim SBAT level is updated (new)
|
||||
|
||||
### Method
|
||||
`Utilities/ShimUtils` includes a script `shim-make.tool` which will download the
|
||||
current Shim source and build it for you, on macOS (using Ubuntu multipass) or on
|
||||
Linux (Ubuntu and Fedora supported, others may work).
|
||||
|
||||
- Extract `vendor.db` and `vendor.dbx` files from the `shimx64.efi` file of each distro
|
||||
which you want to load (using `shim-to-cert.tool`)
|
||||
- For non-GRUB distros, the required public keys for this process cannot be extracted
|
||||
from `shimx64.efi` and so must be found by additional user research
|
||||
- Concatentate these (e.g. `cat fedora/vendor.db ubuntu/vendor.db > combined/vendor.db`
|
||||
and `cat fedora/vendor.dbx ubuntu/vendor.dbx > combined/vendor.dbx`)
|
||||
- Do not concatenate `.der` files directly, it will not work
|
||||
- If you have a single distro with a single `.der` file, you can use `VENDOR_CERT_FILE`
|
||||
instead of `VENDOR_DB_FILE` in the `make` options below; otherwise, you will need to use
|
||||
`cert-to-efi-sig-list` from `efitools` to convert the `.der` file to a sig list - this
|
||||
is done automatically by `shim-to-cert.tool` when `efitools` are available (in
|
||||
Linux; or from within Ubuntu multipass on macOS, e.g. `multipass shell oc-shim`)
|
||||
- Build a version of Shim which includes these concatenated signature lists (and
|
||||
launches OpenCore.efi directly):
|
||||
- `./shim-make.tool setup`
|
||||
- `./shim-make.tool clean` (only needed if remaking after the initial make)
|
||||
- `./shim-make.tool make VENDOR_DB_FILE={full-path-to}/vendor.db VENDOR_DBX_FILE={full-path-to}/vendor.dbx`
|
||||
- On macOS, the paths to these files must either be within the multipass VM, or
|
||||
within a subdirectory visible to macOS and the VM on the same path, such as
|
||||
`/Users/{username}/shim_root` when using `shim-make.tool` default settings
|
||||
- Copy the relevant files (`shimx64.efi` and `mmx64.efi` as well as `BOOTX64.CSV`) to your mounted ESP volume, e.g.:
|
||||
- `./shim-make.tool install /Volumes/EFI` (macOS)
|
||||
- `sudo ./shim-make.tool install /boot/efi` (Linux)
|
||||
- Sign the newly built `shimx64.efi` and `mmx64.efi` with your own ISK (see e.g.
|
||||
https://habr.com/en/articles/273497/ - Google translate is your friend)
|
||||
- If you do not copy and sign `mmx64.efi` as well as `shimx64.efi`, your system will hang if any MOK operations are attempted
|
||||
- `BOOTX64.CSV` is not required and is for information only
|
||||
|
||||
As before you need to sign `OpenCore.efi` and any drivers it loads with your ISK.
|
||||
You now also need to add an empty SBAT section to `OpenCore.efi` before signing it.
|
||||
|
||||
> An empty SBAT section means: 'I'm not part of the system which allocates SBAT names
|
||||
and signs them into boot files, and I don't want this boot file to be revoked by any
|
||||
future SBAT revocations'. Of course, you can still revoke boot files you signed yourself
|
||||
by rotating your own signing keys.
|
||||
|
||||
As noted [here](https://github.com/fwupd/fwupd/issues/2910) and
|
||||
[here](https://github.com/rhboot/shim/issues/376),
|
||||
the [documented](https://github.com/rhboot/shim/blob/main/SBAT.md) method for adding an
|
||||
SBAT section to an already-linked `.efi` file does not work correctly (GNU `objcopy`
|
||||
corrupts the executable). This
|
||||
[third party python script](https://github.com/rhboot/shim/issues/376#issuecomment-1628004034)
|
||||
does work. A suitable command is:
|
||||
|
||||
`pe-add-sections.py -s .sbat <(echo -n) -z .sbat -i OpenCore.efi -o OpenCore_empty_sbat.efi`
|
||||
|
||||
This file then needs to be signed and copied back into place, e.g.:
|
||||
|
||||
`sbsign --key {path-to}/ISK.key --cert {path-to}/ISK.pem OpenCore_empty_sbat.efi --output OpenCore.efi`
|
||||
|
||||
Finally, in order for OpenCore integration with Shim to work correctly
|
||||
`UEFI/Quirks/ShimRetainProtocol` must be enabled in `config.plist`, and
|
||||
`LauncherPath` should be set to `\EFI\OC\shimx64.efi`.
|
||||
|
||||
> Using Ubuntu multipass, it is now possible to operate entirely within macOS for signing,
|
||||
key generation, etc. Note that the `~/shim_root` directory is already shared between
|
||||
macOS and the `oc-shim` multipass VM (under its macOS path, e.g. `/Users/username/shim_root`),
|
||||
and other macOS folders and volumes can be mounted if you wish, e.g.
|
||||
`multipass mount /Volumes/EFI oc-shim:/Volumes/EFI`.
|
||||
132
hackintosh-guide/Utilities/ShimUtils/sbat-info.tool
Executable file
132
hackintosh-guide/Utilities/ShimUtils/sbat-info.tool
Executable file
@@ -0,0 +1,132 @@
|
||||
#!/bin/bash
|
||||
|
||||
# sbat-info.tool - Dump SBAT information from .efi executable, with additional
|
||||
# version and SBAT enforcement level information if the executable is Shim.
|
||||
#
|
||||
# Copyright (c) 2023, Michael Beaton. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LIGHT_GREEN='\033[1;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Note: binutils can simply be placed last on the path in macOS, to provide objcopy but avoid hiding native objdump (this script parses LLVM or GNU objdump output).
|
||||
# Alternatively BINUTILS_PREFIX environment variable can be set to enabled prefixed co-existing GNU tools.
|
||||
command -v "${BINUTILS_PREFIX}"objcopy >/dev/null 2>&1 || { echo >&2 "objcopy not found - please install binutils package or set BINUTILS_PREFIX environment variable."; exit 1; }
|
||||
|
||||
usage () {
|
||||
echo "Usage: $(basename "$0") <efifile>"
|
||||
echo " Display SBAT information, if present, for any .efi executable."
|
||||
echo " If the file is a version of Shim, also dislay Shim version info and SBAT enforcement level."
|
||||
}
|
||||
|
||||
has_section () {
|
||||
"${BINUTILS_PREFIX}"objdump -h "$1" | sed -nr 's/^ *[0-9]+ ([^ ]+).*/\1/p' | grep "$2" 1>/dev/null
|
||||
}
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# https://unix.stackexchange.com/a/84980/340732
|
||||
op_dir=$(mktemp -d 2>/dev/null || mktemp -d -t 'shim_info') || exit 1
|
||||
|
||||
# objcopy and objdump do not like writing to stdout when part of a pipe, so just write to temp files
|
||||
# Note: these get created as empty files even if the section does not exist
|
||||
"${BINUTILS_PREFIX}"objcopy -O binary -j ".sbat" "$1" "${op_dir}/sbat" || { rm -rf "${op_dir}"; exit 1; }
|
||||
"${BINUTILS_PREFIX}"objcopy -O binary -j ".sbatlevel" "$1" "${op_dir}/sbatlevel" || { rm -rf "${op_dir}"; exit 1; }
|
||||
"${BINUTILS_PREFIX}"objcopy -O binary -j ".data.ident" "$1" "${op_dir}/data.ident" || { rm -rf "${op_dir}"; exit 1; }
|
||||
|
||||
if ! has_section "$1" ".data.ident" ; then
|
||||
IS_SHIM=0
|
||||
echo -e "${YELLOW}Shim version info not present (probably not Shim)${NC}"
|
||||
else
|
||||
# Treat this section's presence as enough for the warning colours below
|
||||
IS_SHIM=1
|
||||
FILE_HEADER="$(head -n 1 "${op_dir}/data.ident")"
|
||||
SHIM_HEADER="UEFI SHIM"
|
||||
if [ ! "$FILE_HEADER" = "$SHIM_HEADER" ] ; then
|
||||
echo -e "${RED}!!!Version header found '${FILE_HEADER}' expected '${SHIM_HEADER}'${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Found ${SHIM_HEADER} version header${NC}"
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
VERSION="$(grep -a 'Version' "${op_dir}/data.ident" | sed -n 's/^\$Version: *\([^[:space:]]*\) *\$$/\1/p')"
|
||||
if [ "$VERSION" = "" ] ; then
|
||||
echo -e "${RED}Expected version number not present${NC}"
|
||||
else
|
||||
echo -e "Version: ${LIGHT_GREEN}${VERSION}${NC} (${VERSION}+, if user build)"
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
COMMIT="$(grep -a 'Commit' "${op_dir}/data.ident" | sed -n 's/^\$Commit: *\([^[:space:]]*\) *\$$/\1/p')"
|
||||
if [ "$COMMIT" = "" ] ; then
|
||||
echo -e "${RED}Expected commit id not present${NC}"
|
||||
else
|
||||
echo "Commit: ${COMMIT}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "${YELLOW}SBAT (when tested by other files or by self):${NC}"
|
||||
|
||||
if ! has_section "$1" ".sbat" ; then
|
||||
echo
|
||||
echo -e "${RED}No .sbat section${NC}"
|
||||
else
|
||||
echo
|
||||
echo -n -e "$LIGHT_GREEN"
|
||||
cat "${op_dir}/sbat"
|
||||
echo -n -e "$NC"
|
||||
if ! cat "${op_dir}/sbat" | grep -E "[a-z]|[A-Z]" 1>/dev/null ; then
|
||||
# Red for shim; yellow for other file
|
||||
if [ "$IS_SHIM" -eq 1 ] ; then
|
||||
echo -n -e "$RED"
|
||||
else
|
||||
echo -n -e "$LIGHT_GREEN"
|
||||
fi
|
||||
echo -e "Present but empty .sbat section"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "${YELLOW}SBAT Level (when testing other files):${NC}"
|
||||
|
||||
if ! has_section "$1" ".sbatlevel" ; then
|
||||
echo
|
||||
# Yellow for shim (not present in earlier shims with .sbat, ~15.6); green for other file
|
||||
if [ "$IS_SHIM" -eq 1 ] ; then
|
||||
echo -n -e "$YELLOW"
|
||||
else
|
||||
echo -n -e "$LIGHT_GREEN"
|
||||
fi
|
||||
echo -n "No .sbatlevel section"
|
||||
echo -e "$NC"
|
||||
else
|
||||
sbat_level_version=$(dd if="${op_dir}/sbatlevel" ibs=1 skip=0 count=4 2>/dev/null | od -t u4 -An | xargs) || { rm -rf "${op_dir}"; exit 1; }
|
||||
sbat_level_previous=$(dd if="${op_dir}/sbatlevel" ibs=1 skip=4 count=4 2>/dev/null | od -t u4 -An | xargs) || { rm -rf "${op_dir}"; exit 1; }
|
||||
sbat_level_latest=$(dd if="${op_dir}/sbatlevel" ibs=1 skip=8 count=4 2>/dev/null | od -t u4 -An | xargs) || { rm -rf "${op_dir}"; exit 1; }
|
||||
|
||||
if [ "$sbat_level_version" -ne 0 ] ; then
|
||||
echo -e "${RED}!!! Unexpected .sbatlevel version $sbat_level_version != 0 !!!${NC}"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "${YELLOW}Previous (more permissive boot, default):${NC}"
|
||||
echo -n -e "$LIGHT_GREEN"
|
||||
dd if="${op_dir}/sbatlevel" ibs=1 skip="$(($sbat_level_previous + 4))" count="$(($sbat_level_latest - $sbat_level_previous))" 2>/dev/null
|
||||
echo -e "$NC"
|
||||
|
||||
echo -e "${YELLOW}Latest (stricter boot, optional):${NC}"
|
||||
echo -n -e "$LIGHT_GREEN"
|
||||
dd if="${op_dir}/sbatlevel" ibs=1 skip="$(($sbat_level_latest + 4))" 2>/dev/null
|
||||
echo -e "$NC"
|
||||
fi
|
||||
|
||||
rm -rf "${op_dir}"
|
||||
|
||||
exit 0
|
||||
339
hackintosh-guide/Utilities/ShimUtils/shim-make.tool
Executable file
339
hackintosh-guide/Utilities/ShimUtils/shim-make.tool
Executable file
@@ -0,0 +1,339 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2023 Mike Beaton. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
# Makes user build of shim which launches OpenCore.efi and includes specified vendor certificate lists.
|
||||
# Builds on macOS using Ubuntu multipass or on Linux directly (Ubuntu & Fedora tested).
|
||||
#
|
||||
# To debug shim (e.g. within OVMF) make with
|
||||
# ./shim-make.tool make OPTIMIZATIONS="-O0"
|
||||
# and set 605dab50-e046-4300-abb6-3dd810dd8b23:SHIM_DEBUG to (UINT8)1 (<data>AQ==</data>) in NVRAM
|
||||
#
|
||||
|
||||
ROOT=~/shim_root
|
||||
SHIM=~/shim_source
|
||||
OC_SHIM=oc-shim
|
||||
|
||||
unamer() {
|
||||
NAME="$(uname)"
|
||||
|
||||
if [ "$(echo "${NAME}" | grep MINGW)" != "" ] || [ "$(echo "${NAME}" | grep MSYS)" != "" ]; then
|
||||
echo "Windows"
|
||||
else
|
||||
echo "${NAME}"
|
||||
fi
|
||||
}
|
||||
|
||||
shim_command () {
|
||||
DIR=$1
|
||||
shift
|
||||
if [ $DARWIN -eq 1 ] ; then
|
||||
if [ $ECHO -eq 1 ] ; then
|
||||
# shellcheck disable=SC2068
|
||||
echo multipass exec ${OC_SHIM} --working-directory "'${DIR}'" -- $@ 1>/dev/stderr
|
||||
fi
|
||||
# shellcheck disable=SC2068,SC2294
|
||||
eval multipass exec ${OC_SHIM} --working-directory "'${DIR}'" -- $@
|
||||
else
|
||||
if [ $ECHO -eq 1 ] ; then
|
||||
# shellcheck disable=SC2068
|
||||
echo "[${DIR}]" $@ 1>/dev/stderr
|
||||
fi
|
||||
pushd "${DIR}" 1>/dev/null || exit 1
|
||||
# shellcheck disable=SC2068,SC2294
|
||||
eval $@
|
||||
retval=$?
|
||||
popd 1>/dev/null || exit 1
|
||||
return $retval
|
||||
fi
|
||||
}
|
||||
|
||||
shim_command_v () {
|
||||
FOUND="$(shim_command . command -v "'${1}'" | wc -l)"
|
||||
return $((1 - $FOUND))
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "Usage:"
|
||||
echo -n " ./${SELFNAME} [args] [setup|clean|make [options]|install [esp-root-path]"
|
||||
if [ $DARWIN -eq 1 ] ; then
|
||||
echo -n "|mount [multipass-path]]"
|
||||
fi
|
||||
echo "]"
|
||||
echo
|
||||
echo "Args:"
|
||||
echo -n " -r : Specify shim output root, default '${ROOT}'"
|
||||
if [ $DARWIN -eq 1 ] ; then
|
||||
echo -n " (shared)"
|
||||
fi
|
||||
echo
|
||||
echo -n " -s : Specify shim source location, default '${SHIM}'"
|
||||
if [ $DARWIN -eq 1 ] ; then
|
||||
echo -n " (VM only, unless 'shim-make mount' used for development/debugging)"
|
||||
fi
|
||||
echo
|
||||
echo "If used, -r/-s:"
|
||||
echo " - Should be specified on every call, they are not remembered from 'setup'"
|
||||
echo " - Should come before the chosen command"
|
||||
echo
|
||||
echo "Examples:"
|
||||
echo " ./${SELFNAME} setup (sets up directories and installs rhboot/shim source)"
|
||||
echo " ./${SELFNAME} clean (cleans after previous make)"
|
||||
LOCATION="."
|
||||
if [ $DARWIN -eq 1 ] ; then
|
||||
LOCATION="${ROOT}"
|
||||
fi
|
||||
echo -n " ./${SELFNAME} make VENDOR_DB_FILE='${LOCATION}/combined/vendor.db' VENDOR_DBX_FILE='${LOCATION}/combined/vendor.dbx' (makes shim with db and dbx contents"
|
||||
if [ $DARWIN -eq 1 ] ; then
|
||||
echo -n "; note VENDOR_DB_FILE and VENDOR_DBX_FILE are inside a directory shared with VM"
|
||||
fi
|
||||
echo ")"
|
||||
echo " ./${SELFNAME} install '${EXAMPLE_ESP}' (installs made files to ESP mounted at '${EXAMPLE_ESP}')"
|
||||
echo
|
||||
echo "After installation shimx64.efi and mmx64.efi must be signed by user ISK; OpenCore.efi must have an .sbat section added and be signed by user ISK."
|
||||
}
|
||||
|
||||
mount_path () {
|
||||
SRC=$1
|
||||
if [ "${SRC}" = "" ] ; then
|
||||
echo "Incorrect call to mount_path!"
|
||||
exit 1
|
||||
fi
|
||||
DEST=$2
|
||||
if [ "${DEST}" = "" ] ; then
|
||||
DEST=${SRC}
|
||||
fi
|
||||
|
||||
if [ ! -d "${SRC}" ] ; then
|
||||
echo "Adding ${SRC}..."
|
||||
mkdir -p "${SRC}" || exit 1
|
||||
else
|
||||
echo "${SRC} already present..."
|
||||
fi
|
||||
|
||||
if [ $DARWIN -eq 1 ] ; then
|
||||
if ! multipass info ${OC_SHIM} | grep "${DEST}" 1>/dev/null ; then
|
||||
echo "Mounting ${SRC}..."
|
||||
multipass mount "${SRC}" "${OC_SHIM}:${DEST}" || exit 1
|
||||
else
|
||||
echo "${SRC} already mounted..."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
get_ready () {
|
||||
if [ $DARWIN -eq 1 ] ; then
|
||||
if ! command -v multipass 1>/dev/null ; then
|
||||
echo "Installing Ubuntu multipass..."
|
||||
brew install --cask multipass || exit 1
|
||||
else
|
||||
echo "Ubuntu multipass already installed..."
|
||||
fi
|
||||
|
||||
if ! multipass info ${OC_SHIM} &>/dev/null ; then
|
||||
echo "Launching ${OC_SHIM} multipass instance..."
|
||||
multipass launch -n ${OC_SHIM} || exit 1
|
||||
else
|
||||
echo "${OC_SHIM} multipass instance already launched..."
|
||||
fi
|
||||
fi
|
||||
|
||||
mount_path "${ROOT}"
|
||||
|
||||
if ! shim_command_v gcc || ! shim_command_v make || ! shim_command_v git || ! shim_command_v sbsign || ! shim_command_v sbsiglist ; then
|
||||
echo "Installing dependencies..."
|
||||
if shim_command_v dnf ; then
|
||||
shim_command . sudo dnf install -y gcc make git elfutils-libelf-devel sbsigntools efitools || exit 1
|
||||
else
|
||||
shim_command . sudo apt-get update || exit 1
|
||||
shim_command . sudo apt install -y gcc make git libelf-dev sbsigntool efitools || exit 1
|
||||
fi
|
||||
else
|
||||
echo "Dependencies already installed..."
|
||||
fi
|
||||
|
||||
#
|
||||
# For debug/develop purposes on Darwin it would be nicer to keep the source code in
|
||||
# macOS, just mounted and built in multipass, but the build is about 1/3 the speed of
|
||||
# building in a native multipass directory.
|
||||
# For the purposes of having a fast build but code which can be opened e.g.
|
||||
# within an IDE within macOS, sshfs can be used to mount out from multipass
|
||||
# to macOS using ./shim-make mount:
|
||||
# - https://github.com/canonical/multipass/issues/1070
|
||||
# - https://osxfuse.github.io/
|
||||
#
|
||||
if ! shim_command . test -d "'${SHIM}'" ; then
|
||||
# TODO: Once there is a stable version of Shim containing the commits we need
|
||||
# - 1f38cb30a5e1dcea97b8d48915515b866ec13c32
|
||||
# - a8b0b600ddcf02605da8582b4eac1932a3bb13fa
|
||||
# (i.e. 15.8. hopefully) we should probably check out at a fixed, stable tag, starting
|
||||
# at 15.8 and then manually updated in this script when a new stable version is released,
|
||||
# but which can be overridden with any commit or branch with a script option.
|
||||
echo "Cloning rhboot/shim..."
|
||||
shim_command . git clone https://github.com/rhboot/shim.git "'${SHIM}'" || exit 1
|
||||
shim_command "${SHIM}" git submodule update --init || exit 1
|
||||
else
|
||||
if ! shim_command "${SHIM}" git remote -v | grep "rhboot/shim" 1>/dev/null ; then
|
||||
echo "FATAL: VM subdirectory ${SHIM} is already present, but does not contain rhboot/shim!"
|
||||
exit 1
|
||||
fi
|
||||
echo "rhboot/shim already cloned..."
|
||||
fi
|
||||
|
||||
echo "Make.defaults:"
|
||||
|
||||
# These two modifications to Make.defaults only required for debugging
|
||||
FOUND=$(shim_command "${SHIM}" grep "gdwarf" Make.defaults | wc -l)
|
||||
if [ "$FOUND" -eq 0 ] ; then
|
||||
echo " Updating gdwarf flags..."
|
||||
shim_command "${SHIM}" sed -i "'s^-ggdb \\\\^-ggdb -gdwarf-4 -gstrict-dwarf \\\\^g'" Make.defaults
|
||||
else
|
||||
echo " gdwarf flags already updated..."
|
||||
fi
|
||||
|
||||
FOUND=$(shim_command "${SHIM}" grep "'${ROOT}'" Make.defaults | wc -l)
|
||||
if [ "$FOUND" -eq 0 ] ; then
|
||||
echo " Updating debug directory..."
|
||||
shim_command "${SHIM}" sed -i "\"s^-DDEBUGDIR='L\\\"/usr/lib/debug/usr/share/shim/\\\$(ARCH_SUFFIX)-\\\$(VERSION)\\\$(DASHRELEASE)/\\\"'^-DDEBUGDIR='L\\\"${ROOT}/usr/lib/debug/boot/efi/EFI/OC/\\\"'^g\"" Make.defaults
|
||||
else
|
||||
echo " Debug directory already updated..."
|
||||
fi
|
||||
|
||||
# Work-around for https://github.com/rhboot/shim/issues/596
|
||||
FOUND=$(shim_command "${SHIM}" grep "'export DEFINES'" Make.defaults | wc -l)
|
||||
if [ "$FOUND" -eq 0 ] ; then
|
||||
echo " Updating exports..."
|
||||
|
||||
# var assignment to make output piping work normally
|
||||
# shellcheck disable=SC2034
|
||||
temp=$(echo "export DEFINES" | shim_command "${SHIM}" tee -a Make.defaults) 1>/dev/null
|
||||
else
|
||||
echo " Exports already updated..."
|
||||
fi
|
||||
}
|
||||
|
||||
SELFNAME="$(/usr/bin/basename "${0}")"
|
||||
|
||||
ECHO=0
|
||||
|
||||
if [ "$(unamer)" = "Darwin" ] ; then
|
||||
DARWIN=1
|
||||
EXAMPLE_ESP='/Volumes/EFI'
|
||||
else
|
||||
DARWIN=0
|
||||
EXAMPLE_ESP='/boot/efi'
|
||||
fi
|
||||
|
||||
OPTS=0
|
||||
while [ "${1:0:1}" = "-" ] ; do
|
||||
OPTS=1
|
||||
if [ "$1" = "-r" ] ; then
|
||||
shift
|
||||
if [ "$1" != "" ] && ! [ "${1:0:1}" = "-" ] ; then
|
||||
ROOT=$1
|
||||
shift
|
||||
else
|
||||
echo "No root directory specified" && exit 1
|
||||
fi
|
||||
elif [ "$1" = "-s" ] ; then
|
||||
shift
|
||||
if [ "$1" != "" ] && ! [ "${1:0:1}" = "-" ] ; then
|
||||
SHIM=$1
|
||||
shift
|
||||
else
|
||||
echo "No shim directory specified" && exit 1
|
||||
fi
|
||||
elif [ "$1" = "--echo" ] ; then
|
||||
ECHO=1
|
||||
shift
|
||||
else
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$1" = "setup" ] ; then
|
||||
get_ready
|
||||
echo "Installation complete."
|
||||
exit 0
|
||||
elif [ "$1" = "clean" ] ; then
|
||||
echo "Cleaning..."
|
||||
shim_command "${SHIM}" make clean
|
||||
exit 0
|
||||
elif [ "$1" = "make" ] ; then
|
||||
echo "Making..."
|
||||
shift
|
||||
shim_command "${SHIM}" make DEFAULT_LOADER="\\\\\\\\OpenCore.efi" OVERRIDE_SECURITY_POLICY=1 "$@"
|
||||
exit 0
|
||||
elif [ "$1" = "install" ] ; then
|
||||
echo "Installing..."
|
||||
rm -rf "${ROOT:?}"/usr
|
||||
shim_command "${SHIM}" DESTDIR="'${ROOT}'" EFIDIR='OC' OSLABEL='OpenCore' make install
|
||||
if [ ! "$2" = "" ] ; then
|
||||
echo "Installing to ESP ${2}..."
|
||||
cp "${ROOT}"/boot/efi/EFI/OC/* "${2}"/EFI/OC || exit 1
|
||||
fi
|
||||
exit 0
|
||||
elif [ $DARWIN -eq 1 ] && [ "$1" = "mount" ] ; then
|
||||
MOUNT="$2"
|
||||
if [ "${MOUNT}" = "" ] ; then
|
||||
MOUNT=$SHIM
|
||||
fi
|
||||
|
||||
#
|
||||
# Useful for devel/debug only.
|
||||
# Note: We are only mounting in the reverse direction because we get much faster build speeds.
|
||||
#
|
||||
if ! command -v sshfs 1>/dev/null ; then
|
||||
echo "sshfs (https://osxfuse.github.io/) is required for mounting directories from multipass into macOS (https://github.com/canonical/multipass/issues/1070)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "${MOUNT}" ] ; then
|
||||
echo "Making local directory ${MOUNT}..."
|
||||
mkdir -p "${MOUNT}" || exit 1
|
||||
fi
|
||||
|
||||
ls "${MOUNT}" 1>/dev/null
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "Directory may be mounted but not ready (no authorized key?)"
|
||||
echo "Try: umount ${MOUNT}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if mount | grep ":${MOUNT}" ; then
|
||||
echo "Already mounted at ${MOUNT}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2012
|
||||
if [ "$(ls -A -1 "${MOUNT}" | wc -l)" -ne 0 ] ; then
|
||||
echo "Directory ${MOUNT} is not empty!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IP=$(multipass info ${OC_SHIM} | grep IPv4 | cut -d ":" -f 2 | sed 's/ //g')
|
||||
if [ "${IP}" = "" ] ; then
|
||||
echo "Cannot obtain IPv4 for ${OC_SHIM}"
|
||||
exit 1
|
||||
fi
|
||||
if sshfs "ubuntu@${IP}:$(realpath "${MOUNT}")" "${MOUNT}" ; then
|
||||
echo "Mounted at ${MOUNT}"
|
||||
exit 0
|
||||
else
|
||||
umount "${MOUNT}"
|
||||
echo "Directory cannot be mounted, append your ssh public key to .ssh/authorized_keys in the VM and try again."
|
||||
exit 1
|
||||
fi
|
||||
elif [ "$1" = "" ] ; then
|
||||
if [ $OPTS -eq 0 ] ; then
|
||||
usage
|
||||
else
|
||||
echo "No command specified."
|
||||
fi
|
||||
exit 1
|
||||
else
|
||||
echo "Unkown command: $1"
|
||||
exit 1
|
||||
fi
|
||||
93
hackintosh-guide/Utilities/ShimUtils/shim-to-cert.tool
Executable file
93
hackintosh-guide/Utilities/ShimUtils/shim-to-cert.tool
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shim-to-cert.tool - Extract OEM signing certificate public key (and full db, dbx if present) from GRUB shim file.
|
||||
#
|
||||
# Copyright (c) 2021-2023, Michael Beaton. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LIGHT_GREEN='\033[1;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Note: binutils can be placed last on path in macOS, to provide objcopy but avoid overwriting native tools.
|
||||
command -v "${BINUTILS_PREFIX}"objcopy >/dev/null 2>&1 || { echo >&2 "objcopy not found - please install binutils package or set BINUTILS_PREFIX environment variable."; exit 1; }
|
||||
command -v openssl >/dev/null 2>&1 || { echo >&2 "openssl not found - please install openssl package."; exit 1; }
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $(basename "$0") <shimfile>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sectfile=$(mktemp) || exit 1
|
||||
|
||||
# make certain we have output file name, as objcopy will trash input file without it
|
||||
if [ "x$sectfile" = "x" ]; then
|
||||
echo >&2 "Error creating tempfile!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# extract .vendor_cert section
|
||||
"${BINUTILS_PREFIX}"objcopy -O binary -j .vendor_cert "$1" "$sectfile" || exit 1
|
||||
|
||||
if [ ! -s "$sectfile" ] ; then
|
||||
echo >&2 "No .vendor_cert section in $1."
|
||||
rm "$sectfile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# xargs trims white space
|
||||
vendor_authorized_size=$(dd if="$sectfile" ibs=1 skip=0 count=4 2>/dev/null | od -t u4 -An | xargs) || { rm "$sectfile"; exit 1; }
|
||||
vendor_deauthorized_size=$(dd if="$sectfile" ibs=1 skip=4 count=4 2>/dev/null | od -t u4 -An | xargs) || { rm "$sectfile"; exit 1; }
|
||||
vendor_authorized_offset=$(dd if="$sectfile" ibs=1 skip=8 count=4 2>/dev/null | od -t u4 -An | xargs) || { rm "$sectfile"; exit 1; }
|
||||
vendor_deauthorized_offset=$(dd if="$sectfile" ibs=1 skip=12 count=4 2>/dev/null | od -t u4 -An | xargs) || { rm "$sectfile"; exit 1; }
|
||||
|
||||
# extract cert or db
|
||||
certfile=$(mktemp) || { rm "$sectfile"; exit 1; }
|
||||
|
||||
# extract db
|
||||
if [ "$vendor_authorized_size" -ne "0" ]; then
|
||||
dd if="$sectfile" ibs=1 skip="$vendor_authorized_offset" count="$vendor_authorized_size" 2>/dev/null > "$certfile" || { rm "$sectfile"; rm "$certfile"; exit 1; }
|
||||
fi
|
||||
|
||||
# extract dbx
|
||||
if [ "$vendor_deauthorized_size" -ne "0" ]; then
|
||||
dd if="$sectfile" ibs=1 skip="$vendor_deauthorized_offset" count="$vendor_deauthorized_size" 2>/dev/null > "vendor.dbx" || { rm "$sectfile"; rm "$certfile"; exit 1; }
|
||||
echo -e " - Secure Boot revocation list saved as ${LIGHT_GREEN}vendor.dbx${NC}"
|
||||
else
|
||||
echo " - No secure Boot revocation list"
|
||||
fi
|
||||
|
||||
rm "$sectfile"
|
||||
|
||||
if [ "$vendor_authorized_size" -eq "0" ]; then
|
||||
echo "!!! Empty vendor_authorized section (no secure boot signing certificates present)."
|
||||
rm "$certfile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# valid as single cert?
|
||||
openssl x509 -noout -inform der -in "$certfile" 2>/dev/null
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
cp "$certfile" vendor.db
|
||||
echo -e " - Secure Boot signing list saved as ${LIGHT_GREEN}vendor.db${NC}"
|
||||
else
|
||||
# outfile name from cert CN
|
||||
certname=$(openssl x509 -noout -subject -inform der -in "$certfile" | sed 's/^subject=.*CN *=[ \"]*//' | sed 's/[,\/].*//' | sed 's/ *//g') || { rm "$certfile"; exit 1; }
|
||||
outfile="${certname}.der"
|
||||
|
||||
cp "$certfile" "$outfile" || { rm "$certfile"; exit 1; }
|
||||
|
||||
echo -e " - Secure Boot certificate saved as ${LIGHT_GREEN}${outfile}${NC}"
|
||||
|
||||
if ! command -v cert-to-efi-sig-list >/dev/null ; then
|
||||
echo -e " o To convert certificate to vendor.db use:"
|
||||
echo -e " ${YELLOW}" 'cert-to-efi-sig-list <(openssl x509 -in' "'${outfile}'" '-outform PEM) vendor.db' "${NC}"
|
||||
else
|
||||
cert-to-efi-sig-list <(openssl x509 -in "${outfile}" -outform PEM) vendor.db || { rm "$certfile"; exit 1; }
|
||||
echo -e " o Certificate has also been saved as single cert signing list ${LIGHT_GREEN}vendor.db${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
rm "$certfile"
|
||||
92
hackintosh-guide/Utilities/ShimUtils/unsign-efi-sig-list.tool
Executable file
92
hackintosh-guide/Utilities/ShimUtils/unsign-efi-sig-list.tool
Executable file
@@ -0,0 +1,92 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# unsign-efi-sig-list.tool
|
||||
# Removes signing key from signed certificate list,
|
||||
# also saves signing section and prints CNs found in,
|
||||
# thereby helping to indicate who signed it originally.
|
||||
#
|
||||
# Copyright (c) 2023, Michael Beaton. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
if [ $# -lt 1 ] || [ $# -gt 3 ] ; then
|
||||
echo "Usage:"
|
||||
echo " $(basename "$0") <signed-sig-list> [<outfile> [<sigfile>]]"
|
||||
echo ""
|
||||
echo " - Uses infile name with .unsigned appended if outfile name not specified"
|
||||
echo " - Uses infile name with .pkcs7 appended if sigfile name not specified"
|
||||
echo ""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -f "$1" ] ; then
|
||||
echo "File not found: $1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
infile="$1"
|
||||
shift
|
||||
|
||||
if [ "$1" != "" ] ; then
|
||||
outfile="$1"
|
||||
shift
|
||||
else
|
||||
outfile="${infile}.unsigned"
|
||||
fi
|
||||
|
||||
EfiTimeSize=16
|
||||
WinCertHdrSize=8
|
||||
GuidSize=16
|
||||
ExpectedRevision=$((0x0200))
|
||||
ExpectedCertificateType=$((0x0EF1))
|
||||
|
||||
WinCertificateSize=$(dd if="$infile" ibs=1 skip="$EfiTimeSize" count=4 2>/dev/null | od -t u4 -An | xargs)
|
||||
Revision=$(dd if="$infile" ibs=1 skip="$(($EfiTimeSize + 4))" count=2 2>/dev/null | od -t u4 -An | xargs)
|
||||
CertificateType=$(dd if="$infile" ibs=1 skip="$(($EfiTimeSize + 6))" count=2 2>/dev/null | od -t u4 -An | xargs)
|
||||
|
||||
if [ "$CertificateType" -ne "$ExpectedCertificateType" ] ; then
|
||||
printf "Not a signed certificate file (signature 0x%04X found, 0x%04X expected) in: %s\n" "$CertificateType" "$ExpectedCertificateType" "$infile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$Revision" -ne "$ExpectedRevision" ] ; then
|
||||
printf "Unexpected revision (0x%04X found, 0x%04X expected) in signed certificate file: %s\n" "$Revision" "$ExpectedRevision" "$infile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dd if="$infile" of="$outfile" ibs=1 skip=$(($EfiTimeSize + $WinCertificateSize)) 2>/dev/null
|
||||
|
||||
echo "Unsigned certificate list saved to '$outfile'"
|
||||
|
||||
# Total size is header+guid+sig
|
||||
if [ "$WinCertificateSize" -le "$(($WinCertHdrSize + $GuidSize))" ] ; then
|
||||
echo "!!! Certificate size smaller than expected header size"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# In little-endian byte order
|
||||
EFI_CERT_TYPE_PKCS7_GUID="9dd2af4adf68ee498aa9347d375665a7"
|
||||
|
||||
# Expect pkcs7 sig (diff piping requires bash not sh)
|
||||
if ! diff <(dd if="$infile" ibs=1 skip=$(($EfiTimeSize + $WinCertHdrSize)) count=$(($GuidSize)) 2>/dev/null | xxd -p) <(echo $EFI_CERT_TYPE_PKCS7_GUID) 1>/dev/null ; then
|
||||
echo "!!! EFI_CERT_TYPE_PKCS7_GUID not found"
|
||||
ext=".sig"
|
||||
else
|
||||
ext=".pkcs7"
|
||||
fi
|
||||
|
||||
if [ "$1" != "" ] ; then
|
||||
sigfile="$1"
|
||||
shift
|
||||
else
|
||||
sigfile="${infile}${ext}"
|
||||
fi
|
||||
|
||||
dd if="$infile" of="$sigfile" ibs=1 skip=$(($EfiTimeSize + $WinCertHdrSize + $GuidSize)) count=$(($WinCertificateSize - $WinCertHdrSize - $GuidSize)) 2>/dev/null
|
||||
|
||||
echo "Signing data saved to '$sigfile'"
|
||||
|
||||
# TODO: Figure out which openssl command parses this file at the correct level
|
||||
echo "Signing CNs:"
|
||||
openssl asn1parse -inform der -in "$sigfile" | grep -A1 commonName | grep STRING
|
||||
Reference in New Issue
Block a user