| 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 01e581badb54e3775a47d1e39b0749d2cc2e60b3..143d945acdbf61f35550bf61e729e33e98f50a27 100755
|
| --- a/scripts/image_signing/sign_official_build.sh
|
| +++ b/scripts/image_signing/sign_official_build.sh
|
| @@ -5,7 +5,15 @@
|
| # found in the LICENSE file.
|
|
|
| # Sign the final build image using the "official" keys.
|
| -
|
| +#
|
| +# Prerequisite tools needed in the system path:
|
| +#
|
| +# gbb_utility (from src/platform/vboot_reference)
|
| +# vbutil_kernel (from src/platform/vboot_reference)
|
| +# 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:
|
| @@ -35,6 +43,129 @@ 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() {
|
| + 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.
|
| + 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 |
|
| + sed -e 's/.*dm="\([^"]*\)".*/\1/g' |
|
| + cut -f2- -d,)
|
| + # We extract dm=... portion of the config command line. Here's an example:
|
| + #
|
| + # dm="0 2097152 verity ROOT_DEV HASH_DEV 2097152 1 \
|
| + # sha1 63b7ad16cb9db4b70b28593f825aa6b7825fdcf2"
|
| + #
|
| +
|
| + if [ -z ${dm_config} ]; then
|
| + echo "WARNING: Couldn't grab dm_config. Aborting rootfs hash calculation"
|
| + return
|
| + fi
|
| + local rootfs_sectors=$(echo ${dm_config} | cut -f2 -d' ')
|
| + local root_dev=$(echo ${dm_config} | cut -f4 -d ' ')
|
| + local hash_dev=$(echo ${dm_config} | cut -f5 -d ' ')
|
| + 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}
|
| + local table="vroot none ro,"$(sudo verity create \
|
| + ${verity_depth} \
|
| + ${verity_algorithm} \
|
| + ${rootfs_img} \
|
| + $((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")
|
| +
|
| + # 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 \
|
| + seek=${rootfs_sectors} conv=notrunc
|
| +
|
| + # Re-calculate kernel partition signature and command line.
|
| + local updated_kimage=$(make_temp_file)
|
| + vbutil_kernel --repack ${updated_kimage} \
|
| + --keyblock ${keyblock} \
|
| + --signprivate ${signprivate} \
|
| + --oldblob ${temp_kimage} \
|
| + --config ${temp_config}
|
| +
|
| + replace_image_partition ${image} 2 ${updated_kimage}
|
| + replace_image_partition ${image} 3 ${rootfs_img}
|
| +}
|
| +
|
| +# Extracts the firmware update binaries from the a firmware update
|
| +# shell ball (generated by src/platform/firmware/pack_firmware.sh)
|
| +# Args: INPUT_SCRIPT OUTPUT_DIR
|
| +get_firmwarebin_from_shellball() {
|
| + local input=$1
|
| + local output_dir=$2
|
| + uudecode -o - ${input} | tar -C ${output_dir} -zxf - 2>/dev/null || \
|
| + echo "Extracting firmware autoupdate failed.
|
| +Try re-running with FW_NOUPDATE=1." && exit 1
|
| +}
|
| +
|
| +# Re-sign the firmware AU payload inside the image rootfs with a new keys.
|
| +# Args: IMAGE
|
| +resign_firmware_payload() {
|
| + local image=$1
|
| +
|
| + # 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}
|
| +
|
| + temp_outfd=$(make_temp_file)
|
| + # Replace the root key in the GBB
|
| + # TODO(gauravsh): Remove when we lock down the R/O portion of firmware.
|
| + gbb_utility -s \
|
| + --rootkey=${KEY_DIR}/root_key.vbpubk \
|
| + --recoverykey=${KEY_DIR}/recovery_key.vbpubk \
|
| + ${shellball_dir}/bios.bin ${temp_outfd}
|
| +
|
| + # Resign the firmware with new keys
|
| + ${SCRIPT_DIR}/resign_firmwarefd.sh ${temp_outfd} ${temp_dir}/bios.bin \
|
| + ${KEY_DIR}/firmware_data_key.vbprivk \
|
| + ${KEY_DIR}/firmware.keyblock \
|
| + ${KEY_DIR}/kernel_subkey.vbpubk
|
| +
|
| + # 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 |
|
| + sed -e "s#\(.*\)\ \(.*bios.bin.*\)#${newfd_checksum}\ \2#" > ${temp_version}
|
| + sudo cp ${temp_version} ${shellball_dir}/VERSION
|
| +
|
| + # Re-generate firmware_update.tgz and copy over encoded archive in
|
| + # the original shell ball.
|
| + new_fwblob=$(make_temp_file)
|
| + tar zcf - -C ${shellball_dir} . | \
|
| + uuencode firmware_package.tgz > ${new_fwblob}
|
| + new_shellball=$(make_temp_file)
|
| + cat ${rootfs_dir}/usr/sbin/chromeos-firmwareupdate | \
|
| + sed -e '/^begin .*firmware_package/,/end/D' | \
|
| + cat - ${new_fwblob} >${new_shellball}
|
| + sudo cp ${new_shellball} ${rootfs_dir}/usr/sbin/chromeos-firmwareupdate
|
| + # Force unmount of the image as it is needed later.
|
| + sudo umount -d ${rootfs_dir}
|
| + echo "Re-signed firmware AU payload in $image"
|
| +}
|
|
|
| # Generate the SSD image
|
| sign_for_ssd() {
|
| @@ -51,18 +182,15 @@ sign_for_recovery() {
|
| ${KEY_DIR}/recovery_kernel.keyblock
|
|
|
| # Now generate the installer vblock with the SSD keys.
|
| - temp_kimage=$(mktemp)
|
| - trap "rm -f ${temp_kimage}" EXIT
|
| - temp_out_vb=$(mktemp)
|
| - trap "rm -f ${temp_out_vb}" EXIT
|
| + temp_kimage=$(make_temp_file)
|
| + temp_out_vb=$(make_temp_file)
|
| extract_image_partition ${OUTPUT_IMAGE} 2 ${temp_kimage}
|
| ${SCRIPT_DIR}/resign_kernel_partition.sh ${temp_kimage} ${temp_out_vb} \
|
| ${KEY_DIR}/kernel_data_key.vbprivk \
|
| ${KEY_DIR}/kernel.keyblock
|
|
|
| # Copy the installer vblock to the stateful partition.
|
| - local stateful_dir=$(mktemp -d)
|
| - trap "sudo umount -d $stateful_dir; rm -rf $stateful_dir" EXIT
|
| + local stateful_dir=$(make_temp_dir)
|
| mount_image_partition ${OUTPUT_IMAGE} 1 ${stateful_dir}
|
| sudo cp ${temp_out_vb} ${stateful_dir}/vmlinuz_hd.vblock
|
|
|
| @@ -77,15 +205,26 @@ sign_for_factory_install() {
|
| echo "Output signed factory install image to ${OUTPUT_IMAGE}"
|
| }
|
|
|
| +if [ ! "${FW_NOUPDATE}" == "1" ]; then
|
| + resign_firmware_payload ${INPUT_IMAGE}
|
| +fi
|
| +
|
| if [ "${TYPE}" == "ssd" ]; then
|
| + recalculate_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} \
|
| + ${KEY_DIR}/recovery_kernel.keyblock \
|
| + ${KEY_DIR}/recovery_kernel_data_key.vbprivk
|
| sign_for_recovery
|
| elif [ "${TYPE}" == "install" ]; then
|
| + recalculate_rootfs_hash ${INPUT_IMAGE} \
|
| + ${KEY_DIR}/installer_kernel.keyblock \
|
| + ${KEY_DIR}/recovery_kernel_data_key.vbprivk
|
| sign_for_factory_install
|
| else
|
| echo "Invalid type ${TYPE}"
|
| exit 1
|
| fi
|
| -
|
| -
|
|
|