Skip to content

Commit

Permalink
Tools: Add shim-to-sig.tool
Browse files Browse the repository at this point in the history
  • Loading branch information
mikebeaton committed Sep 28, 2021
1 parent 1ddec32 commit e2819b2
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 0 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ OpenCore Changelog
- Added ability to fully override autodetect Linux boot options
- Added large BaseSystem support in `AdviseFeatures`
- Updated builtin firmware versions for SMBIOS and the rest
- Added tool to extract vendor secure boot certificate from GRUB shim file

#### v0.7.3
- Improved SSDT-PNLF compatibility with CFL+ graphics
Expand Down
110 changes: 110 additions & 0 deletions Utilities/ShimToSig/shim-to-sig.tool
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/bin/sh

# shim-to-sig.tool - Extract OEM public key signature from GRUB shim file.
#
# Copyright (c) 2021, Michael Beaton. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-3-Clause
#

if [ -z "$1" ]; then
echo "Usage: $0 {shimfile}"
exit 1
fi

# require binutils and openssl
command -v objcopy >/dev/null 2>&1 || { echo >&2 "objcopy not found - please install binutils package."; exit 1; }
command -v openssl >/dev/null 2>&1 || { echo >&2 "openssl not found - please install openssl package."; exit 1; }

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
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; }

dd if="$sectfile" ibs=1 skip="$vendor_authorized_offset" count="$vendor_authorized_size" 2>/dev/null > "$certfile" || { rm "$sectfile"; rm "$certfile"; exit 1; }

# 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 "Secure Boot block list found and saved as vendor.dbx."
fi

rm "$sectfile"

# valid as single cert?
openssl x509 -noout -inform der -in "$certfile" 2>/dev/null

if [ $? -ne 0 ]; then
# require efitools
command -v sig-list-to-certs >/dev/null 2>&1 || { echo >&2 "sig-list-to-certs not found - please install efitools package."; rm "$certfile"; exit 1; }

certsdir=$(mktemp -d) || { rm "$certfile"; exit 1; }

sig-list-to-certs "$certfile" "${certsdir}/vendor" 1>/dev/null

if [ $? -ne 0 ]; then
echo >&2 "ERROR: vendor_authorized contents cannot be processed as cert file or dbx."

rm -rf "$certsdir"
rm "$certfile"

exit 1
fi

cp "$certfile" vendor.db
echo "Secure Boot allow list found and saved as vendor.db - single cert may not be sufficient to start distro."

# fails when count .der files != 1
cp "$certsdir"/*.der "$certfile" 2>/dev/null

if [ $? -ne 0 ]; then
certcount=$(find "$certsdir" -maxdepth 1 -name "*.der" | wc -l)

if [ "$certcount" -ne "0" ]; then
cp "$certsdir"/*.der .

echo "Extracted multiple signing keys:"
pwd=$(pwd)
cd "$certsdir" || { rm -rf "$certsdir"; rm "$certfile"; exit 1; }
ls -1 ./*.der
cd "$pwd" || { rm -rf "$certsdir"; rm "$certfile"; exit 1; }
fi

rm -rf "$certsdir"
rm "$certfile"

exit 0
fi

rm -rf "$certsdir"
fi

# 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}.pem"

openssl x509 -inform der -in "$certfile" -out "$outfile" || { rm "$certfile"; exit 1; }

rm "$certfile"

echo "Certificate extracted as ${outfile}."
1 change: 1 addition & 0 deletions build_oc.tool
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ package() {
"CreateVault"
"macrecovery"
"kpdescribe"
"ShimToSig"
)
for utilScpt in "${utilScpts[@]}"; do
cp -r "${selfdir}/Utilities/${utilScpt}" "${dstdir}/Utilities"/ || exit 1
Expand Down

0 comments on commit e2819b2

Please sign in to comment.