1#!/bin/bash -eux 2# Copyright 2014 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 6me=${0##*/} 7TMP="$me.tmp" 8 9# Work in scratch directory 10cd "$OUTDIR" 11 12# Helper utility to modify binary blobs 13REPLACE="${BUILD_RUN}/tests/futility/binary_editor" 14 15# First, let's test the basic functionality 16 17# For simplicity, we'll use the same size for all properties. 18"${FUTILITY}" gbb -c 16,0x10,16,0x10 "${TMP}.blob" 19 20# Flags 21"${FUTILITY}" gbb -s --flags=0xdeadbeef "${TMP}.blob" 22"${FUTILITY}" gbb -g --flags "${TMP}.blob" | grep -i 0xdeadbeef 23 24# HWID length should include the terminating null - this is too long 25if "${FUTILITY}" gbb -s --hwid="0123456789ABCDEF" "${TMP}.blob"; then 26 false; 27fi 28# This works 29"${FUTILITY}" gbb -s --hwid="0123456789ABCDE" "${TMP}.blob" 30# Read it back? 31"${FUTILITY}" gbb -g "${TMP}.blob" | grep "0123456789ABCDE" 32 33# Same kind of tests for the other fields, but they need binary files. 34 35# too long 36dd if=/dev/urandom bs=17 count=1 of="${TMP}.data1.toolong" 37dd if=/dev/urandom bs=17 count=1 of="${TMP}.data2.toolong" 38if "${FUTILITY}" gbb -s --rootkey "${TMP}.data1.toolong" "${TMP}.blob"; 39 then false; fi 40if "${FUTILITY}" gbb -s --recoverykey "${TMP}.data2.toolong" "${TMP}.blob"; 41 then false; fi 42 43# shorter than max should be okay, though 44dd if=/dev/urandom bs=10 count=1 of="${TMP}.data1.short" 45dd if=/dev/urandom bs=10 count=1 of="${TMP}.data2.short" 46"${FUTILITY}" gbb -s \ 47 --rootkey "${TMP}.data1.short" \ 48 --recoverykey "${TMP}.data2.short" "${TMP}.blob" 49# read 'em back 50"${FUTILITY}" gbb -g \ 51 --rootkey "${TMP}.read1" \ 52 --recoverykey "${TMP}.read2" "${TMP}.blob" 53# Verify (but remember, it's short) 54cmp -n 10 "${TMP}.data1.short" "${TMP}.read1" 55cmp -n 10 "${TMP}.data2.short" "${TMP}.read2" 56 57# Okay 58dd if=/dev/urandom bs=16 count=1 of="${TMP}.data1" 59dd if=/dev/urandom bs=16 count=1 of="${TMP}.data2" 60dd if=/dev/urandom bs=16 count=1 of="${TMP}.data3" 61"${FUTILITY}" gbb -s --rootkey "${TMP}.data1" "${TMP}.blob" 62"${FUTILITY}" gbb -s --recoverykey "${TMP}.data2" "${TMP}.blob" 63 64# Read 'em back. 65"${FUTILITY}" gbb -g --rootkey "${TMP}.read1" "${TMP}.blob" 66"${FUTILITY}" gbb -g --recoverykey "${TMP}.read2" "${TMP}.blob" 67# Verify 68cmp "${TMP}.data1" "${TMP}.read1" 69cmp "${TMP}.data2" "${TMP}.read2" 70 71# Basic get and set test using flashrom 72# The implementation requires an FMAP so use a full firmware image 73PEPPY_BIOS="${SCRIPT_DIR}/futility/data/bios_peppy_mp.bin" 74cp "${PEPPY_BIOS}" "${TMP}.full.blob" 75"${FUTILITY}" gbb -s --emulate="${TMP}.full.blob" --flags="0xdeadbeef" 76"${FUTILITY}" gbb -g --emulate="${TMP}.full.blob" --flags | grep -i "0xdeadbeef" 77 78# Okay, creating GBB blobs seems to work. Now let's make sure that corrupted 79# blobs are rejected. 80 81# Danger Will Robinson! We assume that ${TMP}.blob has this binary struct: 82# 83# Field Offset Value 84# 85# signature: 0x0000 $GBB 86# major_version: 0x0004 0x0001 87# minor_version: 0x0006 0x0001 88# header_size: 0x0008 0x00000080 89# flags: 0x000c 0xdeadbeef 90# hwid_offset: 0x0010 0x00000080 91# hwid_size: 0x0014 0x00000010 92# rootkey_offset: 0x0018 0x00000090 93# rootkey_size: 0x001c 0x00000010 94# bmpfv_offset: 0x0020 0x000000a0 95# bmpfv_size: 0x0024 0x00000010 96# recovery_key_offset: 0x0028 0x000000b0 97# recovery_key_size: 0x002c 0x00000010 98# pad: 0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 99# 0x0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 100# 0x0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 101# 0x0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 102# 0x0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 103# (HWID) 0x0080 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 00 104# (rootkey) 0x0090 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 105# (bmpfv) 0x00a0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 106# (recovery_key) 0x00b0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 107# 0x00c0 <EOF> 108# 109 110# bad major_version 111"${REPLACE}" 0x4 2 < "${TMP}.blob" > "${TMP}.blob.bad" 112if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi 113 114# header size too large 115"${REPLACE}" 0x8 0x81 < "${TMP}.blob" > "${TMP}.blob.bad" 116if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi 117 118# header size too small 119"${REPLACE}" 0x8 0x7f < "${TMP}.blob" > "${TMP}.blob.bad" 120if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi 121 122# HWID not null-terminated is invalid 123"${REPLACE}" 0x8f 0x41 < "${TMP}.blob" > "${TMP}.blob.bad" 124if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi 125 126# HWID of length zero is okay 127"${REPLACE}" 0x14 0x00 < "${TMP}.blob" > "${TMP}.blob.ok" 128"${FUTILITY}" gbb "${TMP}.blob.ok" 129# And HWID of length 1 consisting only of '\0' is okay, too. 130"${REPLACE}" 0x14 0x01 < "${TMP}.blob" | "${REPLACE}" 0x80 0x00 \ 131 > "${TMP}.blob.ok" 132"${FUTILITY}" gbb "${TMP}.blob.ok" 133 134# zero-length HWID not null-terminated is invalid 135"${REPLACE}" 0x8f 0x41 < "${TMP}.blob" > "${TMP}.blob.bad" 136if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi 137 138# hwid_offset < GBB_HEADER_SIZE is invalid 139"${REPLACE}" 0x10 0x7f < "${TMP}.blob" > "${TMP}.blob.bad" 140if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi 141"${REPLACE}" 0x10 0x00 < "${TMP}.blob" > "${TMP}.blob.bad" 142if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi 143 144# rootkey_offset < GBB_HEADER_SIZE is invalid 145"${REPLACE}" 0x18 0x7f < "${TMP}.blob" > "${TMP}.blob.bad" 146if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi 147"${REPLACE}" 0x18 0x00 < "${TMP}.blob" > "${TMP}.blob.bad" 148if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi 149 150# recovery_key_offset < GBB_HEADER_SIZE is invalid 151"${REPLACE}" 0x28 0x7f < "${TMP}.blob" > "${TMP}.blob.bad" 152if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi 153"${REPLACE}" 0x28 0x00 < "${TMP}.blob" > "${TMP}.blob.bad" 154if "${FUTILITY}" gbb "${TMP}.blob.bad"; then false; fi 155 156# hwid: offset + size == end of file is okay; beyond is invalid 157"${REPLACE}" 0x14 0x40 < "${TMP}.blob" > "${TMP}.blob.bad" 158"${FUTILITY}" gbb -g "${TMP}.blob.bad" 159"${REPLACE}" 0x14 0x41 < "${TMP}.blob" > "${TMP}.blob.bad" 160if "${FUTILITY}" gbb -g "${TMP}.blob.bad"; then false; fi 161 162# rootkey: offset + size == end of file is okay; beyond is invalid 163"${REPLACE}" 0x1c 0x30 < "${TMP}.blob" > "${TMP}.blob.bad" 164"${FUTILITY}" gbb -g "${TMP}.blob.bad" 165"${REPLACE}" 0x1c 0x31 < "${TMP}.blob" > "${TMP}.blob.bad" 166if "${FUTILITY}" gbb -g "${TMP}.blob.bad"; then false; fi 167 168# recovery_key: offset + size == end of file is okay; beyond is invalid 169"${REPLACE}" 0x2c 0x10 < "${TMP}.blob" > "${TMP}.blob.bad" 170"${FUTILITY}" gbb -g "${TMP}.blob.bad" 171"${REPLACE}" 0x2c 0x11 < "${TMP}.blob" > "${TMP}.blob.bad" 172if "${FUTILITY}" gbb -g "${TMP}.blob.bad"; then false; fi 173 174# hwid_size == 0 doesn't complain, but can't be set 175"${REPLACE}" 0x14 0x00 < "${TMP}.blob" > "${TMP}.blob.bad" 176"${FUTILITY}" gbb -g "${TMP}.blob.bad" 177if "${FUTILITY}" gbb -s --hwid="A" "${TMP}.blob.bad"; then false; fi 178 179# rootkey_size == 0 gives warning, gets nothing, can't be set 180"${REPLACE}" 0x1c 0x00 < "${TMP}.blob" > "${TMP}.blob.bad" 181"${FUTILITY}" gbb -g --rootkey "${TMP}.read1" "${TMP}.blob.bad" 182if "${FUTILITY}" gbb -s --rootkey "${TMP}.data1" "${TMP}.blob.bad"; 183 then false; fi 184 185# recovery_key_size == 0 gives warning, gets nothing, can't be set 186"${REPLACE}" 0x2c 0x00 < "${TMP}.blob" > "${TMP}.blob.bad" 187"${FUTILITY}" gbb -g --recoverykey "${TMP}.read2" "${TMP}.blob.bad" 188if "${FUTILITY}" gbb -s --recoverykey "${TMP}.data2" "${TMP}.blob.bad"; 189 then false; fi 190 191 192# GBB v1.2 adds a sha256 digest field in what was previously padding: 193# 194# hwid_digest: 0x0030 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 195# 0x0040 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 196# pad: 0x0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 197# 0x0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 198# 0x0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 199# (HWID) 0x0080 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 00 200 201# See that the digest is updated properly. 202hwid="123456789ABCDEF" 203"${FUTILITY}" gbb -s --hwid="${hwid}" "${TMP}.blob" 204expect=$(echo -n "$hwid" | sha256sum | cut -d ' ' -f 1) 205[ "$(echo -n "${expect}" | wc -c)" == "64" ] 206"${FUTILITY}" gbb -g --digest "${TMP}.blob" | grep "${expect}" 207 208# Garble the digest, see that it's noticed. 209# (assuming these zeros aren't present) 210"${REPLACE}" 0x33 0x00 0x00 0x00 0x00 0x00 < "${TMP}.blob" > "${TMP}.blob.bad" 211"${FUTILITY}" gbb -g --digest "${TMP}.blob.bad" | grep '0000000000' 212"${FUTILITY}" gbb -g --digest "${TMP}.blob.bad" | grep 'invalid' 213 214# Garble the HWID. The digest is unchanged, but now invalid. 215"${REPLACE}" 0x84 0x70 0x71 0x72 < "${TMP}.blob" > "${TMP}.blob.bad" 216"${FUTILITY}" gbb -g --digest "${TMP}.blob.bad" | grep 'invalid' 217 218# cleanup 219rm -f "${TMP}"* 220exit 0 221