Skip to content

Instantly share code, notes, and snippets.

@ncouture
Last active October 13, 2020 12:09
Show Gist options
  • Save ncouture/d2fd9903e8184fc6594b909a4c1f8fad to your computer and use it in GitHub Desktop.
Save ncouture/d2fd9903e8184fc6594b909a4c1f8fad to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# get-verified-crda-reg-data
# --------------------
# Get CRDA and REGDB tarball and cryptographically verify them,
# retrieving the PGP keys using the Web Key Directory (WKD)
# protocol if they are not already in the keyring.
#
# Configurable parameters
# -----------------------
# Where to download the tarball and verification data.
TARGETDIR="$HOME/cdra-wireless-regdb"
# If you set this to empty value, we'll make a temporary
# directory and fetch the verification keys from the
# Web Key Directory each time. Also, see the USEKEYRING=
# configuration option for an alternative that doesn't
# rely on WKD.
GNUPGHOME="$HOME/.gnupg"
# For CI and other automated infrastructure, you may want to
# create a keyring containing the keys belonging to:
# - [email protected]
# - [email protected]
# - [email protected]
#
# To generate the keyring with these keys, do:
# gpg --export autosigner@ torvalds@ gregkh@ > keyring.gpg
# (or use full keyids for maximum certainty)
#
# Once you have keyring.gpg, install it on your CI system and set
# USEKEYRING to the full path to it. If unset, we generate our own
# from GNUPGHOME.
USEKEYRING=
# Point this at your GnuPG binary version 2.1.11 or above.
# If you are using USEKEYRING, GnuPG-1 will work, too.
GPGBIN="/usr/bin/gpg2"
GPGVBIN="/usr/bin/gpgv2"
# We need a compatible version of sha256sum, too
SHA256SUMBIN="/usr/bin/sha256sum"
# And curl
CURLBIN="/usr/bin/curl"
# And we need the xz binary
XZBIN="/usr/bin/xz"
# And we need lynx
LYNXBIN=/usr/bin/lynx
# You shouldn't need to modify this, unless someone
# other than Linus or Greg start releasing kernels.
DEVKEYS="[email protected] [email protected]"
# Don't add this to DEVKEYS, as it plays a wholly
# different role and is NOT a key that should be used
# to verify kernel tarball signatures (just the checksums).
SHAKEYS="[email protected]"
# We need the locations of the archives and signatures to be downloaded.
CRDA=https://cdn.kernel.org/pub/software/network/crda
REGDB=https://mirrors.edge.kernel.org/pub/software/network/wireless-regdb
if [[ ! -d ${TARGETDIR} ]]; then
echo "${TARGETDIR} does not exist"
mkdir -p ${TARGETDIR}
fi
TARGET="${TARGETDIR}/"
# Do we already have this file?
if [[ -f ${TARGET} ]]; then
echo "File ${TARGETDIR}/${TARGET} already exists."
exit 0
fi
# Start by making sure our environment is sane.
if [[ ! -x ${GPGBIN} ]]; then
echo "Could not find gpg in ${GPGBIN}"
exit 1
fi
if [[ ! -x ${GPGVBIN} ]]; then
echo "Could not find gpgv in ${GPGVBIN}"
exit 1
fi
if [[ ! -x ${LYNXBIN} ]]; then
echo "Could not find lynx in ${LYNXBIN}"
exit 1
fi
# Let's make a safe temporary directory for intermediates
TMPDIR=$(mktemp -d ${TARGETDIR}/tarball-verify.XXXXXXXXX.untrusted)
echo "Using TMPDIR=${TMPDIR}"
# Are we using a keyring?
if [[ -z ${USEKEYRING} ]]; then
if [[ -z ${GNUPGHOME} ]]; then
GNUPGHOME="${TMPDIR}/gnupg"
elif [[ ! -d ${GNUPGHOME} ]]; then
echo "GNUPGHOME directory ${GNUPGHOME} does not exist"
echo -n "Create it? [Y/n]"
read YN
if [[ ${YN} == 'n' ]]; then
echo "Exiting"
rm -rf ${TMPDIR}
exit 1
fi
fi
mkdir -p -m 0700 ${GNUPGHOME}
echo "Making sure we have all the necessary keys"
${GPGBIN} --batch --quiet \
--homedir ${GNUPGHOME} \
--auto-key-locate wkd \
--locate-keys ${DEVKEYS} ${SHAKEYS}
# If this returned non-0, we bail
if [[ $? != "0" ]]; then
$(GPGBIN) --batch --quiet \
--homedir ${GNUPGHOME} \
--auto-key-locate wkd \
--locate-keys ${DEVKEYS} ${SHAKEYS}
fi
if [[ $? != "0" ]]; then
echo "Something went wrong fetching keys"
rm -rf ${TMPDIR}
exit 1
fi
# Make a temporary keyring and set USEKEYRING to it
USEKEYRING=${TMPDIR}/keyring.gpg
${GPGBIN} --batch --export ${DEVKEYS} ${SHAKEYS} > ${USEKEYRING}
fi
# Now we make two keyrings -- one for the autosigner, and
# the other for kernel developers. We do this in order to
# make sure that we never verify kernel tarballs using the
# autosigner keys, only using developer keys.
SHAKEYRING=${TMPDIR}/shakeyring.gpg
${GPGBIN} --batch \
--no-default-keyring --keyring ${USEKEYRING} \
--export ${SHAKEYS} > ${SHAKEYRING}
DEVKEYRING=${TMPDIR}/devkeyring.gpg
${GPGBIN} --batch \
--no-default-keyring --keyring ${USEKEYRING} \
--export ${DEVKEYS} > ${DEVKEYRING}
# Now that we know we can verify them, grab the latest archives released.
for HTTPDIR in ${CRDA} ${REGDB}; do
TXZ=$(${LYNXBIN} -dump -listonly ${HTTPDIR} \
| egrep -o 'http.*.tar.*' \
| tail -1)
SIG=${TXZ/.xz/.sign}
SHA=sha256sums.asc
SHAURL=${HTTPDIR}/${SHA}
SHAFILE=${TMPDIR}/${SHA}
# Before we verify the developer signature, we make sure that the
# tarball matches what is on the kernel.org master. This avoids
# CDN cache poisoning that could, in theory, use vulnerabilities in
# the XZ binary to alter the verification process or compromise the
# system performing the verification.
echo "Downloading the checksums file for ${SHAURL}"
if ! ${CURLBIN} -sL -o ${SHAFILE} ${SHAURL}; then
echo "Failed to download the checksums file"
rm -rf ${TMPDIR}
exit 1
fi
echo "Verifying the checksums file"
COUNT=$(${GPGVBIN} --keyring=${SHAKEYRING} --status-fd=1 ${SHAFILE} \
| grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
if [[ ${COUNT} -lt 2 ]]; then
echo "FAILED to verify the sha256sums.asc file."
rm -rf ${TMPDIR}
exit 1
fi
# Grab only the tarball we want from the full list
SHACHECK=${TMPDIR}/sha256sums.txt
grep ${TXZ##*/} ${SHAFILE} > ${SHACHECK}
# CRDA archives have no signature, skipping
if [[ ! ${TXZ##*/} =~ crda* ]]; then
echo "Downloading the signature file for ${TXZ##*/}"
SIGFILE=${TMPDIR}/${TXZ##*/}
if ! ${CURLBIN} -sL -o ${SIGFILE} ${SIG}; then
echo "Failed to download the signature file"
rm -rf ${TMPDIR}
exit 1
fi
fi
echo "Downloading the XZ tarball for ${TXZ##*/}"
TXZFILEURL=(${TMPDIR}/${TXZ##*/})
if ! ${CURLBIN} -L -o ${TXZFILEURL} ${TXZ}; then
echo "Failed to download the tarball"
rm -rf ${TMPDIR}
exit 1
fi
TXZFILES+=(${TXZFILEURL} )
pushd ${TMPDIR} >/dev/null
echo "Verifying checksum on ${TXZ##*}"
if ! ${SHA256SUMBIN} -c ${SHACHECK}; then
echo "FAILED to verify the downloaded tarball checksum"
popd >/dev/null
rm -rf ${TMPDIR}
exit 1
fi
popd >/dev/null
# TODO: retrieve GPG keys of the CRDA and wireless regdb maintainers
# echo
# echo "Verifying developer signature on the tarball"
# COUNT=$(${XZBIN} -cd ${TXZFILE} \
# | ${GPGVBIN} --keyring=${DEVKEYRING} --status-fd=1 ${SIGFILE} - \
# | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
# if [[ ${COUNT} -lt 2 ]]; then
# echo "FAILED to verify the tarball!"
# rm -rf ${TMPDIR}
# exit 1
# fi
for TARGET in ${TXZFILES[@]}; do
echo "Successfully downloaded and verified ${TARGET}"
echo "${CURLBIN} -sL -o ${HTTPDIR}/${TARGET} ${SHA}"
mv -v ${TARGET} ${TARGETDIR}/
done
done
rm -rfv ${TMPDIR}
echo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment