137522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah#!/bin/bash 237522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah 39137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 437522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# Use of this source code is governed by a BSD-style license that can be 537522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# found in the LICENSE file. 637522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah 737522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# Sign the final build image using the "official" keys. 80c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# 90c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# Prerequisite tools needed in the system path: 100c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# 110c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# gbb_utility (from src/platform/vboot_reference) 120c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# vbutil_kernel (from src/platform/vboot_reference) 130c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# cgpt (from src/platform/vboot_reference) 140c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# dump_kernel_config (from src/platform/vboot_reference) 150c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# verity (from src/platform/verity) 161cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# load_kernel_test (from src/platform/vboot_reference) 171a2e6fc765a13b636d3dd75dc7cae709e9e8d218Gaurav Shah# dumpe2fs 18d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah# sha1sum 1937522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah 2037522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# Load common constants and variables. 2137522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah. "$(dirname "$0")/common.sh" 2237522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah 231cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Print usage string 241cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahusage() { 2537522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah cat <<EOF 268ae7b0e41a1252f98e6662a298efb97624431c44Gaurav ShahUsage: $PROG <type> input_image /path/to/keys/dir [output_image] [version_file] 2737522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahwhere <type> is one of: 2837522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah ssd (sign an SSD image) 291cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah recovery (sign a USB recovery image) 3022bd8b0c29b485ccdaa4f63e6fdac9f097b60aabMike Frysinger factory (sign a factory install image) 3122bd8b0c29b485ccdaa4f63e6fdac9f097b60aabMike Frysinger install (old alias to "factory") 32283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger update_payload (sign a delta update hash) 339c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah firmware (sign a firmware image) 3464bd77e1d8b16f6f182184092114a0d8779bdf52Bill Richardson usb (sign an image to boot directly from USB) 351cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah verify (verify an image including rootfs hashes) 361cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 378ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahoutput_image: File name of the signed output image 388ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahversion_file: File name of where to read the kernel and firmware versions. 398ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah 408ae7b0e41a1252f98e6662a298efb97624431c44Gaurav ShahIf you are signing an image, you must specify an [output_image] and 418ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahoptionally, a [version_file]. 428ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah 4337522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav ShahEOF 44b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger if [[ $# -gt 0 ]]; then 45b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger error "$*" 46b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger exit 1 47b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger fi 48b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger exit 0 491cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah} 501cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 51b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger# Verify we have as many arguments as we expect, else show usage & quit. 52b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger# Usage: 53b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger# check_argc <number args> <exact number> 54b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger# check_argc <number args> <lower bound> <upper bound> 55b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysingercheck_argc() { 56b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger case $# in 57b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger 2) 58b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger if [[ $1 -ne $2 ]]; then 59b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger usage "command takes exactly $2 args" 60b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger fi 61b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger ;; 62b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger 3) 63b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger if [[ $1 -lt $2 || $1 -gt $3 ]]; then 64b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger usage "command takes $2 to $3 args" 65b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger fi 66b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger ;; 67b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger *) 68b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger die "check_argc: incorrect number of arguments" 69b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger esac 70b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger} 7137522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah 7237522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah# Abort on errors. 7337522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahset -e 7437522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah 759dc90d36f8f2e2029adbfece0831c1a840e899caGaurav Shah# Add to the path since some tools reside here and may not be in the non-root 769dc90d36f8f2e2029adbfece0831c1a840e899caGaurav Shah# system path. 779dc90d36f8f2e2029adbfece0831c1a840e899caGaurav ShahPATH=$PATH:/usr/sbin:/sbin 789dc90d36f8f2e2029adbfece0831c1a840e899caGaurav Shah 790500524edda44c770690bb942e916522f1eca5cdGaurav Shah# Make sure the tools we need are available. 801cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahfor prereqs in gbb_utility vbutil_kernel cgpt dump_kernel_config verity \ 81ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah load_kernel_test dumpe2fs sha1sum e2fsck; do 820500524edda44c770690bb942e916522f1eca5cdGaurav Shah type -P "${prereqs}" &>/dev/null || \ 830500524edda44c770690bb942e916522f1eca5cdGaurav Shah { echo "${prereqs} tool not found."; exit 1; } 840500524edda44c770690bb942e916522f1eca5cdGaurav Shahdone 850500524edda44c770690bb942e916522f1eca5cdGaurav Shah 8637522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav ShahTYPE=$1 8737522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav ShahINPUT_IMAGE=$2 8837522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav ShahKEY_DIR=$3 8937522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav ShahOUTPUT_IMAGE=$4 908ae7b0e41a1252f98e6662a298efb97624431c44Gaurav ShahVERSION_FILE=$5 918ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah 928ae7b0e41a1252f98e6662a298efb97624431c44Gaurav ShahFIRMWARE_VERSION=1 938ae7b0e41a1252f98e6662a298efb97624431c44Gaurav ShahKERNEL_VERSION=1 9437522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah 951cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Get current rootfs hash and kernel command line 96d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah# ARGS: IMAGE KERNELPART 971cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahgrab_kernel_config() { 981cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah local image=$1 99d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah local kernelpart=$2 # Kernel partition number to grab. 1001cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah # Grab the existing kernel partition and get the kernel config. 1010c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah temp_kimage=$(make_temp_file) 102d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah extract_image_partition ${image} ${kernelpart} ${temp_kimage} 1031cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah dump_kernel_config ${temp_kimage} 1041cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah} 1051cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 10669b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah# TODO(gauravsh): These are duplicated from chromeos-setimage. We need 10769b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah# to move all signing and rootfs code to one single place where it can be 10869b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah# reused. crosbug.com/19543 10969b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah 11069b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah# get_verity_arg <commandline> <key> -> <value> 11169b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shahget_verity_arg() { 112132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah echo "$1" | sed -n "s/.*\b$2=\([^ \"]*\).*/\1/p" 11369b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah} 11469b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah 11569b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shahis_old_verity_argv() { 11669b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah local depth=$(echo "$1" | cut -f7 -d' ') 11769b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah if [ "$depth" = "0" ]; then 11869b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah return 0 11969b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah fi 12069b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah return 1 12169b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah} 12269b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah 123ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah# Get the dmparams parameters from a kernel config. 124ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shahget_dmparams_from_config() { 125ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah local kernel_config=$1 12696d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom echo ${kernel_config} | sed -nre 's/.*dm="([^"]*)".*/\1/p' 127ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah} 128c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah# Get the verity root digest hash from a kernel config command line. 129c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shahget_hash_from_config() { 130c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah local kernel_config=$1 131ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah local dm_config=$(get_dmparams_from_config "${kernel_config}") 132c8c8dfd90992808a91ce85110218cf1f78fd7f92Paul Taysom local vroot_dev=$(get_dm_slave "${dm_config}" vroot) 13396d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom if is_old_verity_argv "${vroot_dev}"; then 13496d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom echo ${vroot_dev} | cut -f9 -d ' ' 135c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah else 13696d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom echo $(get_verity_arg "${vroot_dev}" root_hexdigest) 137c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah fi 138c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah} 139c0911e27b93eae772088ed09d7a41561b7a5b0b6Gaurav Shah 14096d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# Get the slave device and its args 14196d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# get_dm_ags $dm_config [vboot|vroot] 14296d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# Assumes we have only one slave device per device 14396d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysomget_dm_slave() { 14496d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom local dm=$1 14596d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom local device=$2 14696d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom echo $(echo "${dm}" | sed -nre "s/.*${device}[^,]*,([^,]*).*/\1/p") 14796d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom} 14896d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom 14996d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# Set the slave device and its args for a device 15096d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# get_dm_ags $dm_config [vboot|vroot] args 15196d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom# Assumes we have only one slave device per device 15296d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysomset_dm_slave() { 15396d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom local dm=$1 15496d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom local device=$2 15596d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom local slave=$3 15696d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom echo $(echo "${dm}" | 157f5c62bd7dc1ef3d76d6e5f9119ad73ec95a926d7Paul Taysom sed -nre "s#(.*${device}[^,]*,)([^,]*)(.*)#\1${slave}\3#p") 15896d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom} 15996d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom 160ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav ShahCALCULATED_KERNEL_CONFIG= 161e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te LinCALCULATED_DM_ARGS= 1621cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Calculate rootfs hash of an image 1631cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Args: ROOTFS_IMAGE KERNEL_CONFIG HASH_IMAGE 1641cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# 1651cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# rootfs calculation parameters are grabbed from KERNEL_CONFIG 1661cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# 167e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# Updated dm-verity arguments (to be replaced in kernel config command line) 168e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# with the new hash is stored in $CALCULATED_DM_ARGS and the new hash image is 169e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# written to the file HASH_IMAGE. 1701cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahcalculate_rootfs_hash() { 1711cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah local rootfs_image=$1 1721cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah local kernel_config=$2 1731cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah local hash_image=$3 174ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah local dm_config=$(get_dmparams_from_config "${kernel_config}") 1750c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah 17633c44fc14f6981601d0f0743d0705587d5f11c56Gaurav Shah if [ -z "${dm_config}" ]; then 177ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah echo "WARNING: Couldn't grab dm_config. Aborting rootfs hash calculation." 178ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah return 1 1790c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah fi 18096d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom local vroot_dev=$(get_dm_slave "${dm_config}" vroot) 18169b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah 18269b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah local rootfs_sectors 18369b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah local verity_depth 18469b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah local verity_algorithm 18569b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah local root_dev 18669b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah local hash_dev 187132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah local verity_bin="verity" 18896d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom if is_old_verity_argv "${vroot_dev}"; then 18969b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah # dm="0 2097152 verity ROOT_DEV HASH_DEV 2097152 1 \ 19069b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah # sha1 63b7ad16cb9db4b70b28593f825aa6b7825fdcf2" 19196d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom rootfs_sectors=$(echo ${vroot_dev} | cut -f2 -d' ') 19296d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom verity_depth=$(echo ${vroot_dev} | cut -f7 -d' ') 19396d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom verity_algorithm=$(echo ${vroot_dev} | cut -f8 -d' ') 19496d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom root_dev=$(echo ${vroot_dev} | cut -f4 -d ' ') 19596d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom hash_dev=$(echo ${vroot_dev} | cut -f5 -d ' ') 196132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah # Hack around the fact that the signer needs to use the old version of 197132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah # verity to generate legacy verity kernel parameters. If we find it, 198132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah # we use it. 199132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah type -P "verity-old" &>/dev/null && verity_bin="verity-old" 20069b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah else 20169b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah # Key-value parameters. 20296d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom rootfs_sectors=$(get_verity_arg "${vroot_dev}" hashstart) 20369b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah verity_depth=0 20496d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom verity_algorithm=$(get_verity_arg "${vroot_dev}" alg) 20596d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom root_dev=$(get_verity_arg "${vroot_dev}" payload) 20696d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom hash_dev=$(get_verity_arg "${vroot_dev}" hashtree) 20796d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom salt=$(get_verity_arg "${vroot_dev}" salt) 208132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah fi 209132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah 210132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah local salt_arg 211132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah if [ -n "$salt" ]; then 212132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah salt_arg="salt=$salt" 21369b88dc99b0c3ed12ad66f8df7b65ecc3682204fGaurav Shah fi 2140c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah 2151cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah # Run the verity tool on the rootfs partition. 21696d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom local slave=$(sudo ${verity_bin} mode=create \ 217cba0e83d91b33c3ef9c71fc7dc24c1370e7f3e9aGaurav Shah alg=${verity_algorithm} \ 218cba0e83d91b33c3ef9c71fc7dc24c1370e7f3e9aGaurav Shah payload="${rootfs_image}" \ 219cba0e83d91b33c3ef9c71fc7dc24c1370e7f3e9aGaurav Shah payload_blocks=$((rootfs_sectors / 8)) \ 220132e6e0c8cfa49a470199374e2331e3bb2ea21d6Gaurav Shah hashtree="${hash_image}" ${salt_arg}) 2210c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah # Reconstruct new kernel config command line and replace placeholders. 22296d16de52ebb6785f7d34dcecc030d1b4e3f9c09Paul Taysom slave="$(echo "${slave}" | 2230c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah sed -s "s|ROOT_DEV|${root_dev}|g;s|HASH_DEV|${hash_dev}|")" 224e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin CALCULATED_DM_ARGS="$(set_dm_slave "${dm_config}" vroot "${slave}")" 225e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin CALCULATED_KERNEL_CONFIG="$(echo "${kernel_config}" | 226e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin sed -e 's#\(.*dm="\)\([^"]*\)\(".*\)'"#\1${CALCULATED_DM_ARGS}\3#g")" 2271cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah} 2281cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 229e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# Re-calculate rootfs hash, update rootfs and kernel command line(s). 230e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# Args: IMAGE DM_PARTNO KERN_A_KEYBLOCK KERN_A_PRIVKEY KERN_B_KEYBLOCK \ 231e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# KERN_B_PRIVKEY 232e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# 233e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# The rootfs is hashed by tool 'verity', and the hash data is stored after the 234e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# rootfs. A hash of those hash data (also known as final verity hash) may be 235e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# contained in kernel 2 or kernel 4 command line. 236e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# 237e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# This function reads dm-verity configuration from DM_PARTNO, rebuilds rootfs 238e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# hash, and then resigns kernel A & B by their keyblock and private key files. 2391cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahupdate_rootfs_hash() { 2401cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah local image=$1 # Input image. 241e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local dm_partno="$2" # Partition number of kernel that contains verity args. 242e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local kern_a_keyblock="$3" # Keyblock file for kernel A. 243e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local kern_a_privkey="$4" # Private key file for kernel A. 244e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local kern_b_keyblock="$5" # Keyblock file for kernel B. 245e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local kern_b_privkey="$6" # Private key file for kernel A. 246d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah 247e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin # Note even though there are two kernels, there is one place (after rootfs) 248e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin # for hash data, so we must assume both kernel use same hash algorithm (i.e., 249e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin # DM config). 250e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin echo "Updating rootfs hash and updating config for Kernel partitions" 2511cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 252ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah # If we can't find dm parameters in the kernel config, bail out now. 253e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local kernel_config=$(grab_kernel_config "${image}" "${dm_partno}") 254ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah local dm_config=$(get_dmparams_from_config "${kernel_config}") 255ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah if [ -z "${dm_config}" ]; then 256e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin echo "ERROR: Couldn't grab dm_config from kernel partition ${dm_partno}" 257e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin echo " (config: ${kernel_config})" 258e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin return 1 259ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah fi 260ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah 26104c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin # check and clear need_to_resign tag 26204c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin local rootfs_dir=$(make_temp_dir) 26304c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin mount_image_partition_ro "${image}" 3 "${rootfs_dir}" 26404c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin if has_needs_to_be_resigned_tag "${rootfs_dir}"; then 26504c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin # remount as RW 266d170a9d542dd4770c25d5ed82429a55391d88218Gaurav Shah sudo umount "${rootfs_dir}" 26704c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin mount_image_partition "${image}" 3 "${rootfs_dir}" 26804c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin sudo rm -f "${rootfs_dir}/${TAG_NEEDS_TO_BE_SIGNED}" 26904c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin fi 270d170a9d542dd4770c25d5ed82429a55391d88218Gaurav Shah sudo umount "${rootfs_dir}" 27104c00e19c6fd1d9ad09d2bf5e06518c249d62b31Hung-Te Lin 2721cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah local rootfs_image=$(make_temp_file) 2731cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah extract_image_partition ${image} 3 ${rootfs_image} 2741cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah local hash_image=$(make_temp_file) 2751cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 276aaae959412acc95ba2f4a0b5af44d67186c7a3d2Will Drewry # Disable rw mount support prior to hashing. 277aaae959412acc95ba2f4a0b5af44d67186c7a3d2Will Drewry disable_rw_mount "${rootfs_image}" 278aaae959412acc95ba2f4a0b5af44d67186c7a3d2Will Drewry 279ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah if ! calculate_rootfs_hash "${rootfs_image}" "${kernel_config}" \ 280ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah "${hash_image}"; then 281ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah echo "calculate_rootfs_hash failed!" 282ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah echo "Aborting rootfs hash update!" 283e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin return 1 284ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah fi 285ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah 2861a2e6fc765a13b636d3dd75dc7cae709e9e8d218Gaurav Shah local rootfs_blocks=$(sudo dumpe2fs "${rootfs_image}" 2> /dev/null | 2871cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah grep "Block count" | 2881cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah tr -d ' ' | 2891cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah cut -f2 -d:) 2901cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah local rootfs_sectors=$((rootfs_blocks * 8)) 2910c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah 2920c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah # Overwrite the appended hashes in the rootfs 2931cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah dd if=${hash_image} of=${rootfs_image} bs=512 \ 2946bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah seek=${rootfs_sectors} conv=notrunc 2>/dev/null 295e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin replace_image_partition ${image} 3 ${rootfs_image} 2960c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah 297e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin # Update kernel command lines 298e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local dm_args="${CALCULATED_DM_ARGS}" 299e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local temp_config=$(make_temp_file) 3001cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah local temp_kimage=$(make_temp_file) 3010c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah local updated_kimage=$(make_temp_file) 302e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local kernelpart= 303e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local keyblock= 304e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local priv_key= 305b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin local new_kernel_config= 306e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin 307e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin for kernelpart in 2 4; do 308b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin if ! new_kernel_config="$( 309b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin grab_kernel_config "${image}" "${kernelpart}" 2>/dev/null)" && 310b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin [[ "${kernelpart}" == 4 ]]; then 311b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin # Legacy images don't have partition 4. 312b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin echo "Skipping empty kernel partition 4 (legacy images)." 313b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin continue 314b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin fi 315b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin new_kernel_config="$(echo "${new_kernel_config}" | 316b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin sed -e 's#\(.*dm="\)\([^"]*\)\(".*\)'"#\1${dm_args}\3#g")" 317e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin echo "New config for kernel partition ${kernelpart} is:" 318e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin echo "${new_kernel_config}" | tee "${temp_config}" 319e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin extract_image_partition "${image}" "${kernelpart}" "${temp_kimage}" 320e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin # Re-calculate kernel partition signature and command line. 321e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin if [[ "$kernelpart" == 2 ]]; then 322e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin keyblock="${kern_a_keyblock}" 323e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin priv_key="${kern_a_privkey}" 324e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin else 325e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin keyblock="${kern_b_keyblock}" 326e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin priv_key="${kern_b_privkey}" 327e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin fi 328e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin vbutil_kernel --repack ${updated_kimage} \ 329e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin --keyblock ${keyblock} \ 330e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin --signprivate ${priv_key} \ 331e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin --version "${KERNEL_VERSION}" \ 332e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin --oldblob ${temp_kimage} \ 333e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin --config ${temp_config} 334e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin replace_image_partition ${image} ${kernelpart} ${updated_kimage} 335e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin done 336e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin} 33733c44fc14f6981601d0f0743d0705587d5f11c56Gaurav Shah 338e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# Update the SSD install-able vblock file on stateful partition. 339e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# ARGS: Image 340b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin# This is deprecated because all new images should have a SSD boot-able kernel 341b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin# in partition 4. However, the signer needs to be able to sign new & old images 342b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin# (crbug.com/449450#c13) so we will probably never remove this. 343e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Linupdate_stateful_partition_vblock() { 344e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local image="$1" 345e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local kernb_image="$(make_temp_file)" 346e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local temp_out_vb="$(make_temp_file)" 347b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin 348e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin extract_image_partition "${image}" 4 "${kernb_image}" 349b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin if [[ "$(dump_kernel_config "${kernb_image}" 2>/dev/null)" == "" ]]; then 350b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin echo "Building vmlinuz_hd.vblock from legacy image partition 2." 351b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin extract_image_partition "${image}" 2 "${kernb_image}" 352b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin fi 353b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin 354b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin # vblock should always use kernel keyblock. 355b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin vbutil_kernel --repack "${temp_out_vb}" \ 356b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin --keyblock "${KEY_DIR}/kernel.keyblock" \ 357b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin --signprivate "${KEY_DIR}/kernel_data_key.vbprivk" \ 358b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin --oldblob "${kernb_image}" \ 359b6ebb1ab1c5a181f08b80f9a77434134645bc294Hung-Te Lin --vblockonly 360e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin 361e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin # Copy the installer vblock to the stateful partition. 362e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local stateful_dir=$(make_temp_dir) 363e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin mount_image_partition "${image}" 1 "${stateful_dir}" 364e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin sudo cp ${temp_out_vb} ${stateful_dir}/vmlinuz_hd.vblock 365e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin sudo umount "${stateful_dir}" 3660c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah} 3670c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah 3685f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah# Do a sanity check on the image's rootfs 3695f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah# ARGS: Image 3705f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shahverify_image_rootfs() { 3715f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah local image=$1 3725f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah local rootfs_image=$(make_temp_file) 3735f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah extract_image_partition ${image} 3 ${rootfs_image} 3745f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah # This flips the read-only compatibility flag, so that e2fsck does not 3755f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah # complain about unknown file system capabilities. 3765f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah enable_rw_mount ${rootfs_image} 3775f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah echo "Running e2fsck to check root file system for errors" 3785f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah sudo e2fsck -fn "${rootfs_image}" || 3795f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah { echo "Root file system has errors!" && exit 1;} 3805f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah} 3818ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah 3829137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# Extracts a firmware updater bundle (for firmware image binaries) file 3839137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# (generated by src/platform/firmware/pack_firmware.sh). 3849137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# Args: INPUT_FILE OUTPUT_DIR 3859137e8df481906c7de15d92f639a6129adedd892Hung-Te Linextract_firmware_bundle() { 3869137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin local input="$(readlink -f "$1")" 3879137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin local output_dir="$2" 3889137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin if [ ! -s "${input}" ]; then 3899137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin return 1 3909137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin elif grep -q '^##CUTHERE##' "${input}"; then 3919137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin # Bundle supports self-extraction. 3929137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin "$input" --sb_extract "${output_dir}" || 3939137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin die "Extracting firmware autoupdate (--sb_extract) failed." 39471bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah else 3959137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin # Legacy bundle - try uudecode. 3969137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin uudecode -o - ${input} | tar -C ${output_dir} -zxf - 2>/dev/null || 3979137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin die "Extracting firmware autoupdate failed." 3989137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin fi 3999137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin} 4009137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin 4019137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# Repacks firmware updater bundle content from given folder. 4029137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin# Args: INPUT_DIR TARGET_SCRIPT 4039137e8df481906c7de15d92f639a6129adedd892Hung-Te Linrepack_firmware_bundle() { 4049137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin local input_dir="$1" 4059137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin local target="$(readlink -f "$2")" 4069137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin 4079137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin if [ ! -s "${target}" ]; then 40871bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah return 1 4099137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin elif grep -q '^##CUTHERE##' "${target}"; then 4109137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin # Bundle supports repacking. 4114edc75daa696f9e6fa39205117233ed68dcbed43Mike Frysinger # Workaround issue crosbug.com/p/33719 4124edc75daa696f9e6fa39205117233ed68dcbed43Mike Frysinger sed -i \ 4134edc75daa696f9e6fa39205117233ed68dcbed43Mike Frysinger 's/shar -Q -q -x -m -w/shar -Q -q -x -m --no-character-count/' \ 4144edc75daa696f9e6fa39205117233ed68dcbed43Mike Frysinger "${target}" 4159137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin "$target" --sb_repack "${input_dir}" || 4169137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin die "Updating firmware autoupdate (--sb_repack) failed." 4179137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin else 4189137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin # Legacy bundle using uuencode + tar.gz. 4199137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin # Replace MD5 checksum in the firmware update payload. 4209137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin local newfd_checksum="$(md5sum ${input_dir}/bios.bin | cut -f 1 -d ' ')" 4219137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin local temp_version="$(make_temp_file)" 4229137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin cat ${input_dir}/VERSION | 4239137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin sed -e "s#\(.*\)\ \(.*bios.bin.*\)#${newfd_checksum}\ \2#" > ${temp_version} 4249137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin mv ${temp_version} ${input_dir}/VERSION 4259137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin 4269137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin # Re-generate firmware_update.tgz and copy over encoded archive in 4279137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin # the original shell ball. 4289137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin sed -ine '/^begin .*firmware_package/,/end/D' "$target" 4299137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin tar zcf - -C "${input_dir}" . | 4309137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin uuencode firmware_package.tgz >>"${target}" 43171bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah fi 4320c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah} 4330c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah 4349c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah# Sign a firmware in-place with the given keys. 435aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger# Args: FIRMWARE_IMAGE KEY_DIR FIRMWARE_VERSION [LOEM_OUTPUT_DIR] 4369c783ce3c132491e28efe84751b20d82fc571560Gaurav Shahsign_firmware() { 4379c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah local image=$1 4389c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah local key_dir=$2 4399c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah local firmware_version=$3 440aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger local loem_output_dir=${4:-} 4419c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah 4429c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah local temp_firmware=$(make_temp_file) 4439c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah # Resign the firmware with new keys, also replacing the root and recovery 4449c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah # public keys in the GBB. 445aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger "${SCRIPT_DIR}/sign_firmware.sh" "${image}" "${key_dir}" "${temp_firmware}" \ 446aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger "${firmware_version}" "${loem_output_dir}" 4479c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah # Note: Although sign_firmware.sh may correctly handle specifying the same 4489c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah # output file as the input file, we do not want to rely on it correctly 4499c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah # handing that. Hence, the use of a temporary file. 4509c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah mv ${temp_firmware} ${image} 4519c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah echo "Signed firmware image output to ${image}" 4529c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah} 4539c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah 454283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger# Sign a delta update payload (usually created by paygen). 455283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger# Args: INPUT_IMAGE KEY_DIR OUTPUT_IMAGE 456283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysingersign_update_payload() { 457283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger local image=$1 458283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger local key_dir=$2 459283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger local output=$3 460283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger local key_size key_file="${key_dir}/update_key.pem" 461e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin # Maps key size to verified boot's algorithm id (for pad_digest_utility). 462e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin # Hashing algorithm is always SHA-256. 463283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger local algo algos=( 464283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger [1024]=1 465283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger [2048]=4 466283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger [4096]=7 467283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger [8192]=10 468283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger ) 469283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger 470283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger key_size=$(openssl rsa -text -noout -in "${key_file}" | \ 471283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger sed -n -r '1{s/Private-Key: \(([0-9]*) bit\)/\1/p}') 472283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger algo=${algos[${key_size}]} 473283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger if [[ -z ${algo} ]]; then 474283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger die "Unknown algorithm specified by key_size=${key_size}" 475283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger fi 476283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger 477283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger pad_digest_utility ${algo} "${image}" | \ 478283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger openssl rsautl -sign -pkcs -inkey "${key_file}" -out "${output}" 479283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger} 480283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger 4810c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# Re-sign the firmware AU payload inside the image rootfs with a new keys. 4820c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah# Args: IMAGE 4830c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shahresign_firmware_payload() { 4840c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah local image=$1 4850c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah 486815193daeeef8913dce878e36c6608adb1c56bb5Gaurav Shah if [ -n "${NO_FWUPDATE}" ]; then 487815193daeeef8913dce878e36c6608adb1c56bb5Gaurav Shah echo "Skipping firmware update." 488815193daeeef8913dce878e36c6608adb1c56bb5Gaurav Shah return 489815193daeeef8913dce878e36c6608adb1c56bb5Gaurav Shah fi 490815193daeeef8913dce878e36c6608adb1c56bb5Gaurav Shah 4919137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin # Grab firmware image from the autoupdate bundle (shellball). 4920c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah local rootfs_dir=$(make_temp_dir) 4930c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah mount_image_partition ${image} 3 ${rootfs_dir} 4949137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin local firmware_bundle="${rootfs_dir}/usr/sbin/chromeos-firmwareupdate" 4950c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah local shellball_dir=$(make_temp_dir) 4969137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin 4979137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin # extract_firmware_bundle can fail if the image has no firmware update. 49840837258677fca4b9bfb37b7bfb288baf40831e0Hung-Te Lin if ! extract_firmware_bundle "${firmware_bundle}" "${shellball_dir}"; then 49940837258677fca4b9bfb37b7bfb288baf40831e0Hung-Te Lin # Unmount now to prevent changes. 50040837258677fca4b9bfb37b7bfb288baf40831e0Hung-Te Lin sudo umount "${rootfs_dir}" 50140837258677fca4b9bfb37b7bfb288baf40831e0Hung-Te Lin echo "Didn't find a firmware update. Not signing firmware." 50240837258677fca4b9bfb37b7bfb288baf40831e0Hung-Te Lin return 50340837258677fca4b9bfb37b7bfb288baf40831e0Hung-Te Lin fi 50471bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah echo "Found a valid firmware update shellball." 5050c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah 506aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger local image_file sign_args=() loem_sfx loem_output_dir 507ca8c372e60d249cc49ecaf1d33ace2d53caadfaeHung-Te Lin for image_file in "${shellball_dir}"/bios*.bin; do 508aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger if [[ -e "${KEY_DIR}/loem.ini" ]]; then 509aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger # Extract the extended details from "bios.bin" and use that in the 510aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger # subdir for the keyset. 511aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger loem_sfx=$(sed -r 's:.*/bios([^/]*)[.]bin$:\1:' <<<"${image_file}") 512aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger loem_output_dir="${shellball_dir}/keyset${loem_sfx}" 513aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger sign_args=( "${loem_output_dir}" ) 514aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger mkdir -p "${loem_output_dir}" 515aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger fi 516aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger sign_firmware "${image_file}" "${KEY_DIR}" "${FIRMWARE_VERSION}" \ 517aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger "${sign_args[@]}" 518ca8c372e60d249cc49ecaf1d33ace2d53caadfaeHung-Te Lin done 51942d23c664dbd1334c82b48b504b7d8499955963dGaurav Shah 5209137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin local signer_notes="${shellball_dir}/VERSION.signer" 5219137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin echo "" >"$signer_notes" 5229137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin echo "Signed with keyset in $(readlink -f "${KEY_DIR}") ." >>"$signer_notes" 5230c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah 5240c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah new_shellball=$(make_temp_file) 5259137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin cp -f "${firmware_bundle}" "${new_shellball}" 526bd3dad01b0c2d934462d70eeabb31abcd0310b3fHung-Te Lin chmod a+rx "${new_shellball}" 5279137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin repack_firmware_bundle "${shellball_dir}" "${new_shellball}" 5289137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin sudo cp -f "${new_shellball}" "${firmware_bundle}" 5299137e8df481906c7de15d92f639a6129adedd892Hung-Te Lin sudo chmod a+rx "${firmware_bundle}" 530e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin # Unmount now to flush changes. 531e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin sudo umount "${rootfs_dir}" 5320c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah echo "Re-signed firmware AU payload in $image" 5330c4c9bac3c390445066f08010a753ce76ccb4a5eGaurav Shah} 53437522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah 5351cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Verify an image including rootfs hash using the specified keys. 5361cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shahverify_image() { 5371cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah local rootfs_image=$(make_temp_file) 5381cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah extract_image_partition ${INPUT_IMAGE} 3 ${rootfs_image} 5391cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 5401cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah echo "Verifying RootFS hash..." 541ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah # What we get from image. 542ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah local kernel_config 543ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah # What we calculate from the rootfs. 544ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah local new_kernel_config 545ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah # Depending on the type of image, the verity parameters may 546ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah # exist in either kernel partition 2 or kernel partition 4 547ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah local partnum 548ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah for partnum in 2 4; do 549ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah echo "Considering Kernel partition $partnum" 550ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah kernel_config=$(grab_kernel_config ${INPUT_IMAGE} $partnum) 551ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah local hash_image=$(make_temp_file) 552ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah if ! calculate_rootfs_hash "${rootfs_image}" "${kernel_config}" \ 553ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah "${hash_image}"; then 554ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah echo "Trying next kernel partition." 555ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah continue 556ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah fi 557ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah new_kernel_config="$CALCULATED_KERNEL_CONFIG" 558ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah break 559ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah done 560ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah 561ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah # Note: If calculate_rootfs_hash succeeded above, these should 562ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah # be non-empty. 563ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah expected_hash=$(get_hash_from_config "${new_kernel_config}") 564ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah got_hash=$(get_hash_from_config "${kernel_config}") 565ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah 566ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah if [ -z "${expected_hash}" ] || [ -z "${got_hash}" ]; then 567ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah echo "FAILURE: Couldn't verify RootFS hash on the image." 568c3fe59f72c95597a2d5becc8511e9d5eaf97c391Gaurav Shah exit 1 569c3fe59f72c95597a2d5becc8511e9d5eaf97c391Gaurav Shah fi 570ce6649250583a8f3a7aeac78ee3a00679cf6223dGaurav Shah 5711cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah if [ ! "${got_hash}" = "${expected_hash}" ]; then 5721cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah cat <<EOF 5731cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav ShahFAILED: RootFS hash is incorrect. 5741cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav ShahExpected: ${expected_hash} 5751cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav ShahGot: ${got_hash} 5761cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav ShahEOF 577c3fe59f72c95597a2d5becc8511e9d5eaf97c391Gaurav Shah exit 1 5781cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah else 5791cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah echo "PASS: RootFS hash is correct (${expected_hash})" 5801cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah fi 5811cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 5821cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah # Now try and verify kernel partition signature. 5831cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah set +e 5841cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah local try_key=${KEY_DIR}/recovery_key.vbpubk 5851cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah echo "Testing key verification..." 5861cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah # The recovery key is only used in the recovery mode. 5871cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah echo -n "With Recovery Key (Recovery Mode ON, Dev Mode OFF): " && \ 5881cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 2 >/dev/null 2>&1 && \ 5891cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah echo "YES"; } || echo "NO" 5901cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah echo -n "With Recovery Key (Recovery Mode ON, Dev Mode ON): " && \ 5911cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 3 >/dev/null 2>&1 && \ 5921cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah echo "YES"; } || echo "NO" 5931cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 5941cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah try_key=${KEY_DIR}/kernel_subkey.vbpubk 5951cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah # The SSD key is only used in non-recovery mode. 5961cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah echo -n "With SSD Key (Recovery Mode OFF, Dev Mode OFF): " && \ 5971cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 0 >/dev/null 2>&1 && \ 5981cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah echo "YES"; } || echo "NO" 5991cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah echo -n "With SSD Key (Recovery Mode OFF, Dev Mode ON): " && \ 6001cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 1 >/dev/null 2>&1 && \ 6011cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah echo "YES"; } || echo "NO" 6021cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah set -e 6031cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 6045f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah verify_image_rootfs "${INPUT_IMAGE}" 6055f500b19ba0cdc174a47a68e40f939a4ed69861cGaurav Shah 6061cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah # TODO(gauravsh): Check embedded firmware AU signatures. 6071cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah} 6081cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 609e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# Re-calculate recovery kernel hash. 610e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# Args: IMAGE_BIN 611e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Linupdate_recovery_kernel_hash() { 612276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah image_bin=$1 6136bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah 6146bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah # Update the Kernel B hash in Kernel A command line 6156bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah local old_kerna_config=$(grab_kernel_config "${image_bin}" 2) 6166bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah local new_kernb=$(make_temp_file) 6176bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah extract_image_partition ${image_bin} 4 ${new_kernb} 6186bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah local new_kernb_hash=$(sha1sum ${new_kernb} | cut -f1 -d' ') 6196bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah 6206bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah new_kerna_config=$(make_temp_file) 6216bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah echo "$old_kerna_config" | 6226bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah sed -e "s#\(kern_b_hash=\)[a-z0-9]*#\1${new_kernb_hash}#" \ 6236bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah > ${new_kerna_config} 624d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah echo "New config for kernel partition 2 is" 6256bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah cat ${new_kerna_config} 626d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah 627d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah local temp_kimagea=$(make_temp_file) 628276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah extract_image_partition ${image_bin} 2 ${temp_kimagea} 6296bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah 630d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah # Re-calculate kernel partition signature and command line. 631d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah local updated_kimagea=$(make_temp_file) 632d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah vbutil_kernel --repack ${updated_kimagea} \ 633d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah --keyblock ${KEY_DIR}/recovery_kernel.keyblock \ 634d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah --signprivate ${KEY_DIR}/recovery_kernel_data_key.vbprivk \ 6358ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah --version "${KERNEL_VERSION}" \ 636d7947a197edc905d3f0a14a661de83573dd6c650Gaurav Shah --oldblob ${temp_kimagea} \ 6376bd03d4a88fa049bd72cf18fec701cec1dfc042bGaurav Shah --config ${new_kerna_config} 6388ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah 639276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah replace_image_partition ${image_bin} 2 ${updated_kimagea} 64037522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah} 64137522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah 642e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# Sign an image file with proper keys. 643e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# Args: IMAGE_TYPE INPUT OUTPUT DM_PARTNO KERN_A_KEYBLOCK KERN_A_PRIVKEY \ 644e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# KERN_B_KEYBLOCK KERN_B_PRIVKEY 645e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# 646e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# A ChromiumOS image file (INPUT) always contains 2 partitions (kernel A & B). 647e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# This function will rebuild hash data by DM_PARTNO, resign kernel partitions by 648e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# their KEYBLOCK and PRIVKEY files, and then write to OUTPUT file. Note some 649e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# special images (specified by IMAGE_TYPE, like 'recovery' or 'factory_install') 650e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# may have additional steps (ex, tweaking verity hash or not stripping files) 651e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin# when generating output file. 652e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Linsign_image_file() { 653e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local image_type="$1" 654e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local input="$2" 655e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local output="$3" 656e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local dm_partno="$4" 657e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local kernA_keyblock="$5" 658e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local kernA_privkey="$6" 659e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local kernB_keyblock="$7" 660e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin local kernB_privkey="$8" 661e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin echo "Preparing ${image_type} image..." 662e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin cp "${input}" "${output}" 663e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin resign_firmware_payload "${output}" 664e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin # We do NOT strip /boot for factory installer, since some devices need it to 665e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin # boot EFI. crbug.com/260512 would obsolete this requirement. 666e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin if [[ "${image_type}" != "factory_install" ]]; then 667e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${SCRIPT_DIR}/strip_boot_from_image.sh" --image "${output}" 668e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin fi 669e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin update_rootfs_hash "${output}" "${dm_partno}" \ 670e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${kernA_keyblock}" "${kernA_privkey}" \ 671e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${kernB_keyblock}" "${kernB_privkey}" 672e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin update_stateful_partition_vblock "${output}" 673e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin if [[ "${image_type}" == "recovery" ]]; then 674e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin update_recovery_kernel_hash "${output}" 675e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin fi 676e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin echo "Signed ${image_type} image output to ${output}" 67737522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah} 67837522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah 6791cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah# Verification 680b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysingercase ${TYPE} in 681b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysingerdump_config) 682b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger check_argc $# 2 683b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger for partnum in 2 4; do 684b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger echo "kernel config in partition number ${partnum}:" 685b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger grab_kernel_config "${INPUT_IMAGE}" ${partnum} 686b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger echo 687b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger done 688b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger exit 0 689b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger ;; 690b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysingerverify) 691b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger check_argc $# 2 6921cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah verify_image 693527612e3565be00030a082c262204a0562bc0d4aGaurav Shah exit 0 694b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger ;; 695b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger*) 696b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger # All other signing commands take 4 to 5 args. 697b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger if [ -z "${OUTPUT_IMAGE}" ]; then 698b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger # Friendlier message. 699b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger usage "Missing output image name" 700b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger fi 701b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger check_argc $# 4 5 702b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysinger ;; 703b55c538fca8939e58d20c127a9f42ce4eba7282cMike Frysingeresac 7041cd4cdbbae7cd51d0c0ab247aab53ebc6a8cc8a9Gaurav Shah 7058ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah# If a version file was specified, read the firmware and kernel 7068ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah# versions from there. 7078ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahif [ -n "${VERSION_FILE}" ]; then 7088ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah FIRMWARE_VERSION=$(sed -n 's#^firmware_version=\(.*\)#\1#pg' ${VERSION_FILE}) 7098ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shah KERNEL_VERSION=$(sed -n 's#^kernel_version=\(.*\)#\1#pg' ${VERSION_FILE}) 7108ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahfi 7118ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahecho "Using firmware version: ${FIRMWARE_VERSION}" 7128ae7b0e41a1252f98e6662a298efb97624431c44Gaurav Shahecho "Using kernel version: ${KERNEL_VERSION}" 71371bff41d6f0ff9912b9c56d14ba2ea0dd0331a9cGaurav Shah 714276f846a142a3c2c7c2c575d4403c71eca18a92aGaurav Shah# Make all modifications on output copy. 715e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Linif [[ "${TYPE}" == "ssd" ]]; then 716e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin sign_image_file "SSD" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \ 717e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/kernel.keyblock" "${KEY_DIR}/kernel_data_key.vbprivk" \ 718e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/kernel.keyblock" "${KEY_DIR}/kernel_data_key.vbprivk" 719e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Linelif [[ "${TYPE}" == "usb" ]]; then 720e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin sign_image_file "USB" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \ 721e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/recovery_kernel.keyblock" \ 722e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/recovery_kernel_data_key.vbprivk" \ 723e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/kernel.keyblock" \ 724e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/kernel_data_key.vbprivk" 725e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Linelif [[ "${TYPE}" == "recovery" ]]; then 726e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin sign_image_file "recovery" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 4 \ 727e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/recovery_kernel.keyblock" \ 728e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/recovery_kernel_data_key.vbprivk" \ 729e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/kernel.keyblock" \ 730e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/kernel_data_key.vbprivk" 731e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Linelif [[ "${TYPE}" == "factory" ]] || [[ "${TYPE}" == "install" ]]; then 732e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin sign_image_file "factory_install" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \ 733e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/installer_kernel.keyblock" \ 734e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/installer_kernel_data_key.vbprivk" \ 735e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/kernel.keyblock" \ 736e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Lin "${KEY_DIR}/kernel_data_key.vbprivk" 737e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Linelif [[ "${TYPE}" == "firmware" ]]; then 738aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger if [[ -e "${KEY_DIR}/loem.ini" ]]; then 739aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger echo "LOEM signing not implemented yet for firmware images" 740aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger exit 1 741aa888463b860c2852f3fcb17baf8de395fcca294Mike Frysinger fi 7429c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah cp ${INPUT_IMAGE} ${OUTPUT_IMAGE} 7439c783ce3c132491e28efe84751b20d82fc571560Gaurav Shah sign_firmware ${OUTPUT_IMAGE} ${KEY_DIR} ${FIRMWARE_VERSION} 744e54e656b9f1b8f8f1bbcad86569b4aaf9e8bd594Hung-Te Linelif [[ "${TYPE}" == "update_payload" ]]; then 745283cbf89a9893f3a024809eb7d6c84ed353df6b4Mike Frysinger sign_update_payload ${INPUT_IMAGE} ${KEY_DIR} ${OUTPUT_IMAGE} 74637522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahelse 74737522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah echo "Invalid type ${TYPE}" 74837522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shah exit 1 74937522c9c0ccf48e63e0ab6c2b35b50948d15a003Gaurav Shahfi 750