Skip to content

Commit b3cdd63

Browse files
authored
Merge pull request #24 from flatcar/kai/postinst-sysext
Support OEM systemd-sysext images and Flatcar extensions
2 parents 4f0534c + b883078 commit b3cdd63

10 files changed

+209
-442
lines changed

decode_payload

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
#!/bin/bash
22
set -euo pipefail
33

4-
CHECKINPUT=0
4+
DEBUG="${DEBUG-0}"
5+
CHECKINPUT="${CHECKINPUT-0}"
56
SCRIPTFOLDER="$(dirname "$(readlink -f "$0")")"
67

8+
PROTOPATH="${PROTOPATH-"${SCRIPTFOLDER}"/src/update_engine}"
9+
710
if [ $# -lt 3 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
811
echo "Usage: $0 PUBKEY PAYLOAD OUTPUT [KERNELOUTPUT]"
912
echo "Decodes a payload, writing the decoded payload to stdout and payload information to stderr"
1013
echo "Only one optional kernel payload is supported (the output file will be zero-sized if no payload was found)."
1114
echo "Only a signle signature is supported as only one pubkey is accepted and in the multi-signature case only the second signature is looked at."
1215
echo "Pass CHECKINPUT=1 to process the inline checksums in addition to the final checksum."
16+
echo "Pass PROTOPATH=folder/ to specify the location of a directory with protobuf files."
1317
exit 1
1418
fi
1519

@@ -23,9 +27,11 @@ KERNEL="${4-}"
2327
MLEN=$(dd status=none bs=1 skip=12 count=8 if="${FILE}" | od --endian=big -An -vtu8 -w1024 | tr -d ' ')
2428

2529
# The manifest starts at offset 20 (with tail we do a +1 compared to dd) and we feed it into protoc for decoding (we assume that the text output format is stable)
26-
DESC=$(protoc --decode=chromeos_update_engine.DeltaArchiveManifest --proto_path "${SCRIPTFOLDER}"/src/update_engine "${SCRIPTFOLDER}"/src/update_engine/update_metadata.proto < <({ tail -c +21 "${FILE}" || true ; } |head -c "${MLEN}"))
30+
DESC=$(protoc --decode=chromeos_update_engine.DeltaArchiveManifest --proto_path "${PROTOPATH}" "${PROTOPATH}"/update_metadata.proto < <({ tail -c +21 "${FILE}" || true ; } |head -c "${MLEN}"))
2731

28-
echo "${DESC}" >&2
32+
if [ "${DEBUG}" = 1 ]; then
33+
echo "${DESC}" >&2
34+
fi
2935

3036
# Truncate
3137
true > "${PARTOUT}"
@@ -117,12 +123,18 @@ fi
117123

118124
# The signature protobuf message is at the signature offset
119125
# Decoding the "data" field caues some troubles and needs a workaround below for the dev key
120-
SIGDESC=$(protoc --decode=chromeos_update_engine.Signatures --proto_path "${SCRIPTFOLDER}"/src/update_engine "${SCRIPTFOLDER}"/src/update_engine/update_metadata.proto < <({ tail -c +$((21 + MLEN + SIGOFFSET)) "${FILE}" || true ; } |head -c "${SIGSIZE}"))
121-
echo "${SIGDESC}" >&2
122-
VERSION=2 # Init for the single-signature case, in the many-signature case the first signature ("version 1" but better would be "number 1") is,
123-
# at least for Flatcar production, a dummy and parsing it overwrites this variable with 1 and it will be ignored,
124-
# the second signature is "version 2" and the one we want to check. Even if only one signature is there it becomes "version 2",
125-
# see https://github.com/flatcar/update_engine/blob/c6f566d47d8949632f7f43871eb8d5c625af3209/src/update_engine/payload_signer.cc#L33
126+
SIGDESC=$(protoc --decode=chromeos_update_engine.Signatures --proto_path "${PROTOPATH}" "${PROTOPATH}"/update_metadata.proto < <({ tail -c +$((21 + MLEN + SIGOFFSET)) "${FILE}" || true ; } |head -c "${SIGSIZE}"))
127+
128+
if [ "${DEBUG}" = 1 ]; then
129+
echo "${SIGDESC}" >&2
130+
fi
131+
132+
# The signal "version" is actually the numbering of multiple signatures, it starts at 2 if there is one signature but
133+
# otherwise it starts at 1. We accept the payload if we find a valid signature that we have a pub key for.
134+
# See https://github.com/flatcar/update_engine/blob/c6f566d47d8949632f7f43871eb8d5c625af3209/src/update_engine/payload_signer.cc#L33
135+
# Note that Flatcar production also has a dummy signature with a random key,
136+
# see https://github.com/flatcar/flatcar-build-scripts/blob/821d8da19567e3d1a29dc24f8c822f67df6a5e02/generate_payload#L384
137+
FOUND=false
126138
while IFS= read -r LINE; do
127139
LINE=$(echo "${LINE}" | sed 's/^ *//g')
128140
case "${LINE}" in
@@ -134,17 +146,19 @@ while IFS= read -r LINE; do
134146
# The raw output instead of asn1parse is used to easily extract the sha256 checksum (done by tail -c 32)
135147
# We also calculate the payload hash that the signature was done for, note that it's of course not the whole file but only up to the attached signature itself
136148
PAYLOADHASH=$(head -c "$((20 + MLEN + SIGOFFSET))" "${FILE}" | sha256sum | cut -d ' ' -f 1)
137-
if [ "${VERSION}" = 2 ] && [ "${SIGHEX}" != "${PAYLOADHASH}" ]; then
138-
echo "Signature error" >&2
139-
exit 1
140-
elif [ "${VERSION}" != 2 ]; then
141-
# For Flatcar production this is a dummy signature with a random key,
142-
# see https://github.com/flatcar/flatcar-build-scripts/blob/821d8da19567e3d1a29dc24f8c822f67df6a5e02/generate_payload#L384
143-
echo "Unprocessed 'version ${VERSION}' signature (Payload hash: ${PAYLOADHASH}, SIGDATA: ${SIGDATA})" >&2
149+
if [ "${SIGHEX}" = "${PAYLOADHASH}" ]; then
150+
FOUND=true
151+
echo "Valid signature found (Version: ${VERSION}, Payload Hash: ${PAYLOADHASH})" >&2
152+
else
153+
echo "Signature error (Version: ${VERSION}, Payload Hash: ${PAYLOADHASH}, SIGDATA: ${SIGDATA})" >&2
144154
fi
145155
;;
146156
*) ;;
147157
esac
148158
done <<< "${SIGDESC}"
149159

160+
if [ "${FOUND}" != true ]; then
161+
echo "No valid signature found" >&2
162+
exit 1
163+
fi
150164
echo "Success" >&2

0 commit comments

Comments
 (0)