37
|
1
|
#!/usr/bin/env bash |
3
|
2
|
# get-linux |
21
|
3
|
|
3
|
4
|
# from https://git.kernel.org/pub/scm/linux/kernel/git/mricon/korg-helpers.git/tree/get-verified-tarball |
21
|
5
|
|
|
6
|
# there are minimal modifications to this script - be careful, it |
|
7
|
# pulls from the upstream kernel source archives. |
|
8
|
|
0
|
9
|
# -------------------- |
|
10
|
# Get Linux kernel tarball and cryptographically verify it, |
|
11
|
# retrieving the PGP keys using the Web Key Directory (WKD) |
|
12
|
# protocol if they are not already in the keyring. |
|
13
|
# |
|
14
|
# Pass the kernel version as the only parameter, or |
|
15
|
# we'll grab the latest stable kernel. |
|
16
|
# |
3
|
17
|
# Example: ./get-linux 4.4.145 |
0
|
18
|
# |
|
19
|
# Configurable parameters |
|
20
|
# ----------------------- |
|
21
|
# What kernel version do you want? |
|
22
|
HOST_VER=$(uname -r | cut -d- -f1) |
|
23
|
VER="${1:-$HOST_VER}" |
|
24
|
|
|
25
|
# Where to download the tarball and verification data. |
229
|
26
|
TARGETDIR=${2:-.stash/src/linux-$VER} |
0
|
27
|
|
|
28
|
# For CI and other automated infrastructure, you may want to |
|
29
|
# create a keyring containing the keys belonging to: |
|
30
|
# - autosigner@kernel.org |
|
31
|
# - torvalds@kernel.org |
|
32
|
# - gregkh@kernel.org |
|
33
|
# |
|
34
|
# To generate the keyring with these keys, do: |
|
35
|
# gpg --export autosigner@ torvalds@ gregkh@ > keyring.gpg |
|
36
|
# (or use full keyids for maximum certainty) |
|
37
|
# |
|
38
|
# Once you have keyring.gpg, install it on your CI system and set |
|
39
|
# USEKEYRING to the full path to it. If unset, we generate our own |
|
40
|
# from GNUPGHOME. |
|
41
|
# need to run make linux-keys first |
|
42
|
USEKEYRING=${3} |
|
43
|
|
|
44
|
# If you set this to empty value, we'll make a temporary |
|
45
|
# directory and fetch the verification keys from the |
|
46
|
# Web Key Directory each time. Also, see the USEKEYRING= |
|
47
|
# configuration option for an alternative that doesn't |
|
48
|
# rely on WKD. |
|
49
|
GNUPGHOME="$HOME/.gnupg" |
|
50
|
|
|
51
|
# Point this at your GnuPG binary version 2.1.11 or above. |
|
52
|
# If you are using USEKEYRING, GnuPG-1 will work, too. |
|
53
|
GPGBIN="/usr/bin/gpg2" |
|
54
|
GPGVBIN="/usr/bin/gpgv2" |
|
55
|
# We need a compatible version of sha256sum, too |
|
56
|
SHA256SUMBIN="/usr/bin/sha256sum" |
|
57
|
# And curl |
|
58
|
CURLBIN="/usr/bin/curl" |
|
59
|
# And we need the xz binary |
|
60
|
XZBIN="/usr/bin/xz" |
|
61
|
|
|
62
|
# You shouldn't need to modify this, unless someone |
|
63
|
# other than Linus or Greg start releasing kernels. |
|
64
|
DEVKEYS="torvalds@kernel.org gregkh@kernel.org" |
|
65
|
# Don't add this to DEVKEYS, as it plays a wholly |
|
66
|
# different role and is NOT a key that should be used |
|
67
|
# to verify kernel tarball signatures (just the checksums). |
|
68
|
SHAKEYS="autosigner@kernel.org" |
|
69
|
|
|
70
|
if [[ -z ${VER} ]]; then |
|
71
|
# Assume you want the latest stable |
|
72
|
VER=$(${CURLBIN} -sL https://www.kernel.org/finger_banner \ |
|
73
|
| grep 'latest stable version' \ |
|
74
|
| awk -F: '{gsub(/ /,"", $0); print $2}') |
|
75
|
fi |
|
76
|
if [[ -z ${VER} ]]; then |
|
77
|
echo "Could not figure out the latest stable version." |
|
78
|
exit 1 |
|
79
|
fi |
|
80
|
|
|
81
|
MAJOR="$(echo ${VER} | cut -d. -f1)" |
|
82
|
if [[ ${MAJOR} -lt 3 ]]; then |
|
83
|
echo "This script only supports kernel v3.x.x and above" |
|
84
|
exit 1 |
|
85
|
fi |
|
86
|
|
|
87
|
if [[ ! -d ${TARGETDIR} ]]; then |
|
88
|
echo "${TARGETDIR} does not exist" |
|
89
|
exit 1 |
|
90
|
fi |
|
91
|
|
|
92
|
TARGET="${TARGETDIR}/linux-${VER}.tar.xz" |
|
93
|
# Do we already have this file? |
|
94
|
if [[ -f ${TARGET} ]]; then |
|
95
|
echo "File ${TARGETDIR}/linux-${VER}.tar.xz already exists." |
|
96
|
exit 0 |
|
97
|
fi |
|
98
|
|
|
99
|
# Start by making sure our GnuPG environment is sane |
|
100
|
if [[ ! -x ${GPGBIN} ]]; then |
|
101
|
echo "Could not find gpg in ${GPGBIN}" |
|
102
|
exit 1 |
|
103
|
fi |
|
104
|
if [[ ! -x ${GPGVBIN} ]]; then |
|
105
|
echo "Could not find gpgv in ${GPGVBIN}" |
|
106
|
exit 1 |
|
107
|
fi |
|
108
|
|
3
|
109
|
# NOTE 2023-11-19: we make a folder in /tmp/ due to a strange bug |
|
110
|
# encountered when using the TARGETDIR. Need to test on |
|
111
|
TMPDIR=$(mktemp -d) |
0
|
112
|
echo "Using TMPDIR=${TMPDIR}" |
|
113
|
# Are we using a keyring? |
|
114
|
if [[ -z ${USEKEYRING} ]]; then |
|
115
|
if [[ -z ${GNUPGHOME} ]]; then |
|
116
|
GNUPGHOME="${TMPDIR}/gnupg" |
|
117
|
elif [[ ! -d ${GNUPGHOME} ]]; then |
|
118
|
echo "GNUPGHOME directory ${GNUPGHOME} does not exist" |
|
119
|
echo -n "Create it? [Y/n]" |
|
120
|
read YN |
|
121
|
if [[ ${YN} == 'n' ]]; then |
|
122
|
echo "Exiting" |
|
123
|
rm -rf ${TMPDIR} |
|
124
|
exit 1 |
|
125
|
fi |
|
126
|
fi |
|
127
|
mkdir -p -m 0700 ${GNUPGHOME} |
|
128
|
echo "Making sure we have all the necessary keys" |
|
129
|
${GPGBIN} --batch --quiet \ |
|
130
|
--homedir ${GNUPGHOME} \ |
|
131
|
--auto-key-locate wkd \ |
|
132
|
--locate-keys ${DEVKEYS} ${SHAKEYS} |
|
133
|
# If this returned non-0, we bail |
|
134
|
if [[ $? != "0" ]]; then |
|
135
|
echo "Something went wrong fetching keys" |
|
136
|
rm -rf ${TMPDIR} |
|
137
|
exit 1 |
|
138
|
fi |
|
139
|
# Make a temporary keyring and set USEKEYRING to it |
|
140
|
USEKEYRING=${TMPDIR}/keyring.gpg |
|
141
|
${GPGBIN} --batch --export ${DEVKEYS} ${SHAKEYS} > ${USEKEYRING} |
|
142
|
fi |
|
143
|
# Now we make two keyrings -- one for the autosigner, and |
|
144
|
# the other for kernel developers. We do this in order to |
|
145
|
# make sure that we never verify kernel tarballs using the |
|
146
|
# autosigner keys, only using developer keys. |
|
147
|
SHAKEYRING=${TMPDIR}/shakeyring.gpg |
|
148
|
${GPGBIN} --batch \ |
|
149
|
--no-default-keyring --keyring ${USEKEYRING} \ |
|
150
|
--export ${SHAKEYS} > ${SHAKEYRING} |
|
151
|
DEVKEYRING=${TMPDIR}/devkeyring.gpg |
|
152
|
${GPGBIN} --batch \ |
|
153
|
--no-default-keyring --keyring ${USEKEYRING} \ |
|
154
|
--export ${DEVKEYS} > ${DEVKEYRING} |
|
155
|
|
|
156
|
# Now that we know we can verify them, grab the contents |
|
157
|
TXZ="https://cdn.kernel.org/pub/linux/kernel/v${MAJOR}.x/linux-${VER}.tar.xz" |
|
158
|
SIG="https://cdn.kernel.org/pub/linux/kernel/v${MAJOR}.x/linux-${VER}.tar.sign" |
|
159
|
SHA="https://www.kernel.org/pub/linux/kernel/v${MAJOR}.x/sha256sums.asc" |
|
160
|
|
|
161
|
# Before we verify the developer signature, we make sure that the |
|
162
|
# tarball matches what is on the kernel.org master. This avoids |
|
163
|
# CDN cache poisoning that could, in theory, use vulnerabilities in |
|
164
|
# the XZ binary to alter the verification process or compromise the |
|
165
|
# system performing the verification. |
|
166
|
SHAFILE=${TMPDIR}/sha256sums.asc |
|
167
|
echo "Downloading the checksums file for linux-${VER}" |
|
168
|
if ! ${CURLBIN} -sL -o ${SHAFILE} ${SHA}; then |
|
169
|
echo "Failed to download the checksums file" |
|
170
|
rm -rf ${TMPDIR} |
|
171
|
exit 1 |
|
172
|
fi |
|
173
|
echo "Verifying the checksums file" |
|
174
|
COUNT=$(${GPGVBIN} --keyring=${SHAKEYRING} --status-fd=1 ${SHAFILE} \ |
|
175
|
| grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)') |
|
176
|
if [[ ${COUNT} -lt 2 ]]; then |
|
177
|
echo "FAILED to verify the sha256sums.asc file." |
|
178
|
rm -rf ${TMPDIR} |
|
179
|
exit 1 |
|
180
|
fi |
|
181
|
# Grab only the tarball we want from the full list |
|
182
|
SHACHECK=${TMPDIR}/sha256sums.txt |
|
183
|
grep "linux-${VER}.tar.xz" ${SHAFILE} > ${SHACHECK} |
|
184
|
|
|
185
|
echo |
|
186
|
echo "Downloading the signature file for linux-${VER}" |
|
187
|
SIGFILE=${TMPDIR}/linux-${VER}.tar.asc |
|
188
|
if ! ${CURLBIN} -sL -o ${SIGFILE} ${SIG}; then |
|
189
|
echo "Failed to download the signature file" |
|
190
|
rm -rf ${TMPDIR} |
|
191
|
exit 1 |
|
192
|
fi |
|
193
|
echo "Downloading the XZ tarball for linux-${VER}" |
|
194
|
TXZFILE=${TMPDIR}/linux-${VER}.tar.xz |
|
195
|
if ! ${CURLBIN} -L -o ${TXZFILE} ${TXZ}; then |
|
196
|
echo "Failed to download the tarball" |
|
197
|
rm -rf ${TMPDIR} |
|
198
|
exit 1 |
|
199
|
fi |
|
200
|
|
|
201
|
pushd ${TMPDIR} >/dev/null |
|
202
|
echo "Verifying checksum on linux-${VER}.tar.xz" |
|
203
|
if ! ${SHA256SUMBIN} -c ${SHACHECK}; then |
|
204
|
echo "FAILED to verify the downloaded tarball checksum" |
|
205
|
popd >/dev/null |
|
206
|
rm -rf ${TMPDIR} |
|
207
|
exit 1 |
|
208
|
fi |
|
209
|
popd >/dev/null |
|
210
|
|
|
211
|
echo |
|
212
|
echo "Verifying developer signature on the tarball" |
|
213
|
COUNT=$(${XZBIN} -cd ${TXZFILE} \ |
|
214
|
| ${GPGVBIN} --keyring=${DEVKEYRING} --status-fd=1 ${SIGFILE} - \ |
|
215
|
| grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)') |
|
216
|
if [[ ${COUNT} -lt 2 ]]; then |
|
217
|
echo "FAILED to verify the tarball!" |
|
218
|
rm -rf ${TMPDIR} |
|
219
|
exit 1 |
|
220
|
fi |
|
221
|
mv -f ${TXZFILE} ${TARGET} |
|
222
|
rm -rf ${TMPDIR} |
|
223
|
echo |
|
224
|
echo "Successfully downloaded and verified ${TARGET}" |