Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(475)

Unified Diff: scripts/image_signing/sign_official_build.sh

Issue 3327005: Add a "verify" option to sign_official_build.sh. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/vboot_reference.git
Patch Set: nosudo Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « scripts/image_signing/common.sh ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: scripts/image_signing/sign_official_build.sh
diff --git a/scripts/image_signing/sign_official_build.sh b/scripts/image_signing/sign_official_build.sh
index cdc1837af02251e48681aeb20c4ff4630b108665..d7140acc64de660223ae159924903c914b8b6cfc 100755
--- a/scripts/image_signing/sign_official_build.sh
+++ b/scripts/image_signing/sign_official_build.sh
@@ -13,25 +13,27 @@
# cgpt (from src/platform/vboot_reference)
# dump_kernel_config (from src/platform/vboot_reference)
# verity (from src/platform/verity)
-#
-# Usage: sign_for_ssd.sh <type> input_image /path/to/keys/dir output_image
-#
-# where <type> is one of:
-# ssd (sign an SSD image)
-# recovery (sign a USB recovery image)
-# install (sign a factory install image)
+# load_kernel_test (from src/platform/vboot_reference)
# Load common constants and variables.
. "$(dirname "$0")/common.sh"
-if [ $# -ne 4 ]; then
+# Print usage string
+usage() {
cat <<EOF
-Usage: $0 <type> input_image /path/to/keys/dir output_image"
+Usage: $PROG <type> input_image /path/to/keys/dir [output_image]
where <type> is one of:
ssd (sign an SSD image)
- recovery (sign a USB recovery image)
- install (sign a factory install image)
+ recovery (sign a USB recovery image)
+ install (sign a factory install image)
+ verify (verify an image including rootfs hashes)
+
+If you are signing an image, you must specify an [output_image].
EOF
+}
+
+if [ $# -ne 3 ] && [ $# -ne 4 ]; then
+ usage
exit 1
fi
@@ -39,7 +41,9 @@ fi
set -e
# Make sure the tools we need are available.
-for prereqs in gbb_utility vbutil_kernel cgpt dump_kernel_config verity; do
+for prereqs in gbb_utility vbutil_kernel cgpt dump_kernel_config verity \
+ load_kernel_test;
+do
type -P "${prereqs}" &>/dev/null || \
{ echo "${prereqs} tool not found."; exit 1; }
done
@@ -49,19 +53,35 @@ INPUT_IMAGE=$2
KEY_DIR=$3
OUTPUT_IMAGE=$4
-# Re-calculate rootfs hash, update rootfs and kernel command line.
-# Args: IMAGE KEYBLOCK PRIVATEKEY
-recalculate_rootfs_hash() {
- echo "Recalculating rootfs"
- local image=$1 # Input image.
- local keyblock=$2 # Keyblock for re-generating signed kernel partition
- local signprivate=$3 # Private key to use for signing.
-
- # First, grab the existing kernel partition and get the kernel config.
+# Get current rootfs hash and kernel command line
+# ARGS: IMAGE
+grab_kernel_config() {
+ local image=$1
+ # Grab the existing kernel partition and get the kernel config.
temp_kimage=$(make_temp_file)
extract_image_partition ${image} 2 ${temp_kimage}
- local kernel_config=$(sudo dump_kernel_config ${temp_kimage})
- local dm_config=$(echo $kernel_config |
+ dump_kernel_config ${temp_kimage}
+}
+
+# Get the hash from a kernel config command line
+get_hash_from_config() {
+ local kernel_config=$1
+ echo ${kernel_config} | sed -e 's/.*dm="\([^"]*\)".*/\1/g' | \
+ cut -f2- -d, | cut -f9 -d ' '
+}
+
+# Calculate rootfs hash of an image
+# Args: ROOTFS_IMAGE KERNEL_CONFIG HASH_IMAGE
+#
+# rootfs calculation parameters are grabbed from KERNEL_CONFIG
+#
+# Returns an updated kernel config command line with the new hash.
+# and writes the new hash image to the file HASH_IMAGE
+calculate_rootfs_hash() {
+ local rootfs_image=$1
+ local kernel_config=$2
+ local hash_image=$3
+ local dm_config=$(echo ${kernel_config} |
sed -e 's/.*dm="\([^"]*\)".*/\1/g' |
cut -f2- -d,)
# We extract dm=... portion of the config command line. Here's an example:
@@ -72,7 +92,7 @@ recalculate_rootfs_hash() {
if [ -z "${dm_config}" ]; then
echo "WARNING: Couldn't grab dm_config. Aborting rootfs hash calculation"
- return
+ exit 1
fi
local rootfs_sectors=$(echo ${dm_config} | cut -f2 -d' ')
local root_dev=$(echo ${dm_config} | cut -f4 -d ' ')
@@ -80,28 +100,49 @@ recalculate_rootfs_hash() {
local verity_depth=$(echo ${dm_config} | cut -f7 -d' ')
local verity_algorithm=$(echo ${dm_config} | cut -f8 -d' ')
- # Mount the rootfs and run the verity tool on it.
- local hash_image=$(make_temp_file)
- local rootfs_img=$(make_temp_file)
- extract_image_partition ${image} 3 ${rootfs_img}
+ # Run the verity tool on the rootfs partition.
local table="vroot none ro,"$(sudo verity create \
${verity_depth} \
${verity_algorithm} \
- ${rootfs_img} \
+ ${rootfs_image} \
$((rootfs_sectors / 8)) \
${hash_image})
# Reconstruct new kernel config command line and replace placeholders.
table="$(echo "$table" |
sed -s "s|ROOT_DEV|${root_dev}|g;s|HASH_DEV|${hash_dev}|")"
- kernel_config=$(echo ${kernel_config} |
- sed -e 's#\(.*dm="\)\([^"]*\)\(".*\)'"#\1${table}\3#g")
+ echo ${kernel_config} | sed -e 's#\(.*dm="\)\([^"]*\)\(".*\)'"#\1${table}\3#g"
+}
+
+# Re-calculate rootfs hash, update rootfs and kernel command line.
+# Args: IMAGE KEYBLOCK PRIVATEKEY
+update_rootfs_hash() {
+ echo "Recalculating rootfs"
+ local image=$1 # Input image.
+ local keyblock=$2 # Keyblock for re-generating signed kernel partition
+ local signprivate=$3 # Private key to use for signing.
+
+ local rootfs_image=$(make_temp_file)
+ extract_image_partition ${image} 3 ${rootfs_image}
+ local kernel_config=$(grab_kernel_config "${image}")
+ local hash_image=$(make_temp_file)
+
+ local new_kernel_config=$(calculate_rootfs_hash "${rootfs_image}" \
+ "${kernel_config}" "${hash_image}")
+
+ local rootfs_blocks=$(dumpe2fs "${rootfs_image}" 2> /dev/null |
+ grep "Block count" |
+ tr -d ' ' |
+ cut -f2 -d:)
+ local rootfs_sectors=$((rootfs_blocks * 8))
# Overwrite the appended hashes in the rootfs
local temp_config=$(make_temp_file)
- echo ${kernel_config} >${temp_config}
- dd if=${hash_image} of=${rootfs_img} bs=512 \
+ echo ${new_kernel_config} >${temp_config}
+ dd if=${hash_image} of=${rootfs_image} bs=512 \
seek=${rootfs_sectors} conv=notrunc
+ local temp_kimage=$(make_temp_file)
+ extract_image_partition ${image} 2 ${temp_kimage}
# Re-calculate kernel partition signature and command line.
local updated_kimage=$(make_temp_file)
vbutil_kernel --repack ${updated_kimage} \
@@ -111,7 +152,7 @@ recalculate_rootfs_hash() {
--config ${temp_config}
replace_image_partition ${image} 2 ${updated_kimage}
- replace_image_partition ${image} 3 ${rootfs_img}
+ replace_image_partition ${image} 3 ${rootfs_image}
}
# Extracts the firmware update binaries from the a firmware update
@@ -119,7 +160,7 @@ recalculate_rootfs_hash() {
# Args: INPUT_SCRIPT OUTPUT_DIR
get_firmwarebin_from_shellball() {
local input=$1
- local output_dir=$2
+ local output_dir=$2
uudecode -o - ${input} | tar -C ${output_dir} -zxf - 2>/dev/null || \
echo "Extracting firmware autoupdate failed." && exit 1
}
@@ -132,7 +173,7 @@ resign_firmware_payload() {
# Grab firmware image from the autoupdate shellball.
local rootfs_dir=$(make_temp_dir)
mount_image_partition ${image} 3 ${rootfs_dir}
-
+
local shellball_dir=$(make_temp_dir)
get_firmwarebin_from_shellball \
${rootfs_dir}/usr/sbin/chromeos-firmwareupdate ${shellball_dir}
@@ -154,7 +195,7 @@ resign_firmware_payload() {
# Replace MD5 checksum in the firmware update payload
newfd_checksum=$(md5sum ${shellball_dir}/bios.bin | cut -f 1 -d ' ')
temp_version=$(make_temp_file)
- cat ${shellball_dir}/VERSION |
+ cat ${shellball_dir}/VERSION |
sed -e "s#\(.*\)\ \(.*bios.bin.*\)#${newfd_checksum}\ \2#" > ${temp_version}
sudo cp ${temp_version} ${shellball_dir}/VERSION
@@ -173,6 +214,57 @@ resign_firmware_payload() {
echo "Re-signed firmware AU payload in $image"
}
+# Verify an image including rootfs hash using the specified keys.
+verify_image() {
+ local kernel_config=$(grab_kernel_config ${INPUT_IMAGE})
+ local rootfs_image=$(make_temp_file)
+ extract_image_partition ${INPUT_IMAGE} 3 ${rootfs_image}
+ local hash_image=$(make_temp_file)
+ local type=""
+
+
+ # First, perform RootFS verification
+ echo "Verifying RootFS hash..."
+ local new_kernel_config=$(calculate_rootfs_hash "${rootfs_image}" \
+ "${kernel_config}" "${hash_image}")
+ local expected_hash=$(get_hash_from_config "${new_kernel_config}")
+ local got_hash=$(get_hash_from_config "${kernel_config}")
+
+ if [ ! "${got_hash}" = "${expected_hash}" ]; then
+ cat <<EOF
+FAILED: RootFS hash is incorrect.
+Expected: ${expected_hash}
+Got: ${got_hash}
+EOF
+ else
+ echo "PASS: RootFS hash is correct (${expected_hash})"
+ fi
+
+ # Now try and verify kernel partition signature.
+ set +e
+ local try_key=${KEY_DIR}/recovery_key.vbpubk
+ echo "Testing key verification..."
+ # The recovery key is only used in the recovery mode.
+ echo -n "With Recovery Key (Recovery Mode ON, Dev Mode OFF): " && \
+ { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 2 >/dev/null 2>&1 && \
+ echo "YES"; } || echo "NO"
+ echo -n "With Recovery Key (Recovery Mode ON, Dev Mode ON): " && \
+ { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 3 >/dev/null 2>&1 && \
+ echo "YES"; } || echo "NO"
+
+ try_key=${KEY_DIR}/kernel_subkey.vbpubk
+ # The SSD key is only used in non-recovery mode.
+ echo -n "With SSD Key (Recovery Mode OFF, Dev Mode OFF): " && \
+ { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 0 >/dev/null 2>&1 && \
+ echo "YES"; } || echo "NO"
+ echo -n "With SSD Key (Recovery Mode OFF, Dev Mode ON): " && \
+ { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 1 >/dev/null 2>&1 && \
+ echo "YES"; } || echo "NO"
+ set -e
+
+ # TODO(gauravsh): Check embedded firmware AU signatures.
+}
+
# Generate the SSD image
sign_for_ssd() {
${SCRIPT_DIR}/resign_image.sh ${INPUT_IMAGE} ${OUTPUT_IMAGE} \
@@ -185,7 +277,7 @@ sign_for_ssd() {
sign_for_recovery() {
${SCRIPT_DIR}/resign_image.sh ${INPUT_IMAGE} ${OUTPUT_IMAGE} \
${KEY_DIR}/recovery_kernel_data_key.vbprivk \
- ${KEY_DIR}/recovery_kernel.keyblock
+ ${KEY_DIR}/recovery_kernel.keyblock
# Now generate the installer vblock with the SSD keys.
temp_kimage=$(make_temp_file)
@@ -217,18 +309,31 @@ if [ "${FW_UPDATE}" == "1" ]; then
resign_firmware_payload ${INPUT_IMAGE}
fi
+# Verification
+if [ "${TYPE}" == "verify" ]; then
+ verify_image
+ exit 1
+fi
+
+
+# Signing requires an output image name
+if [ -z "${OUTPUT_IMAGE}" ]; then
+ usage
+ exit 1
+fi
+
if [ "${TYPE}" == "ssd" ]; then
- recalculate_rootfs_hash ${INPUT_IMAGE} \
+ update_rootfs_hash ${INPUT_IMAGE} \
${KEY_DIR}/kernel.keyblock \
${KEY_DIR}/kernel_data_key.vbprivk
sign_for_ssd
elif [ "${TYPE}" == "recovery" ]; then
- recalculate_rootfs_hash ${INPUT_IMAGE} \
+ update_rootfs_hash ${INPUT_IMAGE} \
${KEY_DIR}/recovery_kernel.keyblock \
${KEY_DIR}/recovery_kernel_data_key.vbprivk
sign_for_recovery
elif [ "${TYPE}" == "install" ]; then
- recalculate_rootfs_hash ${INPUT_IMAGE} \
+ update_rootfs_hash ${INPUT_IMAGE} \
${KEY_DIR}/installer_kernel.keyblock \
${KEY_DIR}/recovery_kernel_data_key.vbprivk
sign_for_factory_install
« no previous file with comments | « scripts/image_signing/common.sh ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698