1#!/bin/bash -eux 2# Copyright 2022 The ChromiumOS Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6if [[ -z ${SCRIPT_DIR+x} ]]; then 7 # must be running standalone 8 SCRIPT_DIR="$(readlink -f "$(dirname "$0")"/..)" 9 FUTILITY="${SCRIPT_DIR}/../build/futility/futility" 10fi 11 12if [[ ! -e ${FUTILITY} ]]; then 13 echo "The futility app not available, run 'make futil' in the top directory" \ 14 >&2 15 exit 1 16fi 17 18KEYS_DIR="$(readlink -f "${SCRIPT_DIR}/devkeys")" 19TMPD="$(mktemp -d /tmp/"$(basename "$0")".XXXXX)" 20trap '/bin/rm -rf "${TMPD}"' EXIT 21 22# Test FMAP sections were taken from Nivviks image, which is 32M in size. 23FW_IMAGE_SIZE_K=$(( 32 * 1024 )) 24 25# FMAP offset in the original image 26FMAP_OFFSET_K=28696 27 28main() { 29 local bios_blob 30 local command_args 31 local warn 32 local fmap_blob 33 local hwid 34 local pubkhash 35 local section 36 local stderr_output 37 38 cd "${SCRIPT_DIR}/futility" 39 40 # Create a blob of the firmware image size. 41 bios_blob="${TMPD}/image.bin" 42 cat /dev/zero | tr '\000' '\377' | \ 43 dd of="${bios_blob}" bs=1K count="${FW_IMAGE_SIZE_K}" status=none 44 45 # Paste the FMAP blob at the known location 46 fmap_blob="data/nivviks.FMAP" 47 dd if="${fmap_blob}" of="${bios_blob}" bs=1K seek="${FMAP_OFFSET_K}" \ 48 conv=notrunc status=none 49 50 # Paste other available FMAP areas into the image. 51 command_args=() 52 for section in data/nivviks.[A-Z]*; do 53 local name 54 55 if [[ ${section} =~ .*FMAP ]]; then 56 continue 57 fi 58 59 name="${section##*.}" 60 command_args+=( "${name}:${section}" ) 61 done 62 "${FUTILITY}" load_fmap "${bios_blob}" "${command_args[@]}" 63 64 # Make sure gbb flags are nonzero 65 "${FUTILITY}" gbb --set --flags=1 "${bios_blob}" 66 67 # Sign the blob using ranges already present in the RO_GSCVD section. 68 "${FUTILITY}" gscvd --keyblock "${KEYS_DIR}"/arv_platform.keyblock \ 69 --platform_priv "${KEYS_DIR}"/arv_platform.vbprivk \ 70 --board_id XYZ1 \ 71 --root_pub_key "${KEYS_DIR}"/arv_root.vbpubk "${bios_blob}" 72 73 # Calculate root pub key hash 74 pubkhash="$( "${FUTILITY}" gscvd --root_pub_key \ 75 "${KEYS_DIR}"/arv_root.vbpubk | tail -1)" 76 77 # Message printed on stderr in case signature matches only after zeroing GBB 78 # flags. 79 warn="WARNING: validate_gscvd: Ranges digest matches with zeroed GBB flags" 80 81 # Run verification, this one is expected to succeed but report GBB flags 82 # mismatch. 83 stderr_output=$("${FUTILITY}" gscvd "${bios_blob}" "${pubkhash}" 2>&1) 84 if [[ $? != 0 ]] ; then 85 echo "Unexpected failure with nonzero GBB!" >&2 86 exit 1 87 fi 88 if [[ ${stderr_output} != "${warn}" ]]; then 89 echo "Unexpected error message \"${stderr_output}\" with nonzero GBB!" 90 exit 1 91 fi 92 93 # Clear the flags and try verifying again, should succeed this time. 94 "${FUTILITY}" gbb --set --flags=0 "${bios_blob}" 95 if ! "${FUTILITY}" gscvd "${bios_blob}" "${pubkhash}" 2>/dev/null ; then 96 echo "Unexpected signature MISmatch!" >&2 97 exit 1 98 fi 99 100 # Change HWID and see that signature still matches. 101 hwid="$("${FUTILITY}" gbb --hwid "${bios_blob}" | sed 's/.*: //')" 102 "${FUTILITY}" gbb --set --hwid="${hwid}xx" "${bios_blob}" 103 if ! "${FUTILITY}" gscvd "${bios_blob}" "${pubkhash}" 2>/dev/null ; then 104 echo "Unexpected signature MISmatch after modifying HWID!" >&2 105 exit 1 106 fi 107 108 # Modify the recovery key and see that signature verification fails. 109 "${FUTILITY}" gbb --set \ 110 --recoverykey="${KEYS_DIR}"/recovery_kernel_data_key.vbpubk \ 111 "${bios_blob}" 112 if "${FUTILITY}" gscvd "${bios_blob}" "${pubkhash}" 2>/dev/null ; then 113 echo "Unexpected signature match after updating recovery key!" >&2 114 exit 1 115 fi 116} 117 118main "$@" 119