Last active
October 13, 2020 12:09
-
-
Save ncouture/d2fd9903e8184fc6594b909a4c1f8fad to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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