You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
343 lines
6.7 KiB
343 lines
6.7 KiB
#!/bin/sh -u |
|
# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
|
# Use of this source code is governed by a BSD-style license that can be |
|
# found in the LICENSE file. |
|
# |
|
# Test the chromeos TPM recovery script by faking the entire execution |
|
# environment. |
|
|
|
rm -rf tpm-recovery-test-workdir |
|
mkdir tpm-recovery-test-workdir |
|
cd tpm-recovery-test-workdir |
|
|
|
test_kind= |
|
if [ $# -ge 1 ]; then |
|
test_kind="$1" |
|
fi |
|
|
|
if [ "$test_kind" != "" -a "$test_kind" != "fake" ]; then |
|
echo "$0: usage: $0 [fake]" |
|
echo "With fake as the argument, use a simulated TPM instead of the real one" |
|
fi |
|
|
|
if [ "$test_kind" = "fake" ]; then |
|
export USR_BIN=. |
|
export USR_SBIN=. |
|
export USR_LOCAL_BIN=. |
|
export USR_LOCAL_SBIN=. |
|
export DOT_RECOVERY=.recovery |
|
export ACPI_DIR=. |
|
ctr=../chromeos-tpm-recovery |
|
tpmc=./tpmc |
|
else |
|
ctr=chromeos-tpm-recovery |
|
tpmc=tpmc |
|
fi |
|
|
|
# For simplicity, build the permanent environment as if we prepared to run the |
|
# fake test, even if we're running the test on a real TPM. |
|
|
|
echo > .recovery |
|
echo 3 > BINF.0 |
|
echo 0 > CHSW |
|
|
|
export NVRAM_SPACE_OVERHEAD=200 |
|
space_overhead=$NVRAM_SPACE_OVERHEAD |
|
|
|
# build tpmc |
|
cat > tpmc <<"EOF" |
|
#!/bin/sh -u |
|
# Fake tpmc program |
|
|
|
definespace () { |
|
index=$2 |
|
size=$3 |
|
permissions=$4 |
|
space_overhead=$NVRAM_SPACE_OVERHEAD |
|
|
|
if [ -e space.$index.data -a -e tpm-owned ]; then |
|
echo "cannot redefine space without auth" |
|
fi |
|
|
|
totalsize=$(( $size + $space_overhead )) |
|
free=$(cat nvram.freespace) |
|
|
|
if [ $totalsize -gt $free ]; then |
|
return 17 # NO_SPACE |
|
fi |
|
|
|
if [ $index != 0xf004 ]; then |
|
echo $size > space.$index.size |
|
echo $permissions > space.$index.perm |
|
for i in $(seq 1 $(($size))); do |
|
echo -n "ff " >> space.$index.data |
|
done |
|
echo $(( $free - $totalsize )) > nvram.freespace |
|
fi |
|
return 0 |
|
} |
|
|
|
case $1 in |
|
|
|
clear) |
|
rm -f tpm-owned |
|
;; |
|
|
|
enable) |
|
# boring |
|
;; |
|
|
|
activate) |
|
# boring |
|
;; |
|
|
|
definespace) |
|
definespace $* |
|
;; |
|
|
|
getp) |
|
echo space blah has permissions $(cat space.$2.perm) |
|
;; |
|
|
|
read) |
|
index=$2 |
|
size=$3 |
|
maxsize=$(cat space.$index.size) |
|
if [ $(($size > $maxsize)) -eq 1 ]; then |
|
echo "size $size too large for space (max is $maxsize)" |
|
exit 1 |
|
fi |
|
dd if=space.$index.data bs=1 count=$(($3 * 3)) 2> /dev/null |
|
;; |
|
|
|
write) |
|
args="$@" |
|
index=$2 |
|
bytes="$(echo $args | sed 's/[^ ]* [^ ]* //')" |
|
size=$(echo $bytes | wc -w) |
|
maxsize=$(cat space.$index.size) |
|
if [ $(($size > $maxsize)) -eq 1 ]; then |
|
echo "size $size too large for space (max is $(($maxsize)))" |
|
exit 1 |
|
fi |
|
re=$(echo "$bytes " | sed 's/././g') |
|
sed "s/$re/$bytes /" < space.$index.data > _tmp_ |
|
mv _tmp_ space.$index.data |
|
;; |
|
|
|
getpf) |
|
echo "disable 0" |
|
echo "deactivated 0" |
|
echo "nvLocked 1" |
|
echo "physicalPresenceLifetimeLock 1" |
|
echo "physicalPresenceHWEnable 0" |
|
echo "physicalPresenceCMDEnable 1" |
|
;; |
|
|
|
getvf) |
|
echo "bGlobalLock 1" |
|
echo "physicalPresence 1" |
|
echo "physicalPresenceLock 0" |
|
;; |
|
|
|
ppfin) |
|
# boring |
|
;; |
|
|
|
ppon) |
|
# boring |
|
;; |
|
|
|
*) |
|
echo "tpmc: invalid command $1" |
|
exit 1 |
|
;; |
|
esac |
|
|
|
EOF |
|
|
|
# build nvtool |
|
cat > tpm-nvtool <<"EOF" |
|
#!/bin/sh -u |
|
|
|
space_overhead=$NVRAM_SPACE_OVERHEAD |
|
|
|
print_space () { |
|
local index=$1 |
|
printf "# NV Index 0x%08x" $(( $index )) |
|
echo " uninteresting random garbage" |
|
echo " further random garbage" |
|
echo "" |
|
} |
|
|
|
if [ "$1" = "--release" ]; then |
|
if [ "$2" != "--index" -o \ |
|
"$4" != "--owner_password" ]; then |
|
echo "sorry, picky tpm-nvtool" |
|
exit 1 |
|
fi |
|
index=$3 |
|
if [ ! -f tpm-owned ]; then |
|
echo "tpm is unowned" |
|
exit 1 |
|
fi |
|
size=$(cat space.$index.size) |
|
free=$(cat nvram.freespace) |
|
rm space.$index.* |
|
echo $(( $size + $space_overhead + $free )) > nvram.freespace |
|
elif [ "$1" = "--list" ]; then |
|
for s in space.*.data; do |
|
print_space $(echo $s | sed -e "s/[^.]*\.//" -e "s/\..*//") |
|
done |
|
fi |
|
EOF |
|
|
|
# build tpm_takeownership |
|
cat > tpm_takeownership <<"EOF" |
|
#!/bin/sh -u |
|
if [ -f tpm-owned ]; then |
|
echo "tpm is already owned" |
|
exit 1 |
|
fi |
|
echo > tpm-owned |
|
EOF |
|
|
|
# build tcsd |
|
cat > tcsd <<"EOF" |
|
#!/bin/sh -u |
|
trap "{ rm tcsd_is_running; }" EXIT |
|
echo > tcsd_is_running |
|
sleep 365d |
|
EOF |
|
|
|
tcsd_pid=0 |
|
|
|
start_tcsd () { |
|
if [ $tcsd_pid -ne 0 ]; then |
|
echo TCSD is already started |
|
exit 1 |
|
fi |
|
tcsd -f & |
|
tcsd_pid=$! |
|
sleep 2 |
|
} |
|
|
|
stop_tcsd () { |
|
if [ $tcsd_pid -eq 0 ]; then |
|
echo TCSD is already stopped |
|
exit 1 |
|
fi |
|
kill $tcsd_pid |
|
sleep 0.5 |
|
kill $tcsd_pid > /dev/null 2>&1 |
|
sleep 0.5 |
|
wait $tcsd_pid > /dev/null 2>&1 # we trust that tcsd will agree to die |
|
tcsd_pid=0 |
|
} |
|
|
|
tpm_clear_and_reenable () { |
|
tpmc clear |
|
tpmc enable |
|
tpmc activate |
|
} |
|
|
|
takeownership () { |
|
if [ "$test_kind" = "fake" ]; then |
|
touch tpm_owned |
|
else |
|
tpm_clear_and_reenable |
|
start_tcsd |
|
tpm_takeownership -y -z |
|
stop_tcsd |
|
fi |
|
} |
|
|
|
remove_chromeos_spaces () { |
|
if [ "$test_kind" = "fake" ]; then |
|
rm -f space.* |
|
echo 1500 > nvram.freespace |
|
else |
|
takeownership |
|
start_tcsd |
|
tpm-nvtool --release --index 0x1007 --owner_password "" |
|
tpm-nvtool --release --index 0x1008 --owner_password "" |
|
stop_tcsd |
|
tpm_clear_and_reenable |
|
fi |
|
} |
|
|
|
chmod 755 tpmc tpm-nvtool tpm_takeownership tcsd |
|
|
|
echo "starting test, results in $(pwd)/log" |
|
echo "starting TPM recovery test" > log |
|
|
|
if ps ax | grep "tcs[d]"; then |
|
echo "a tcsd is process appears to be running, please kill it first" |
|
exit 1 |
|
fi |
|
|
|
# normal run |
|
test_normal_run () { |
|
echo "TEST: normal run" >> log |
|
|
|
remove_chromeos_spaces |
|
$tpmc definespace 0x1007 0xa 0x8001 |
|
$tpmc definespace 0x1008 0xd 0x1 |
|
$tpmc write 0x1008 01 4c 57 52 47 |
|
takeownership |
|
|
|
$ctr log |
|
} |
|
|
|
# Kernel space with wrong ID |
|
test_wrong_id () { |
|
echo "TEST: bad kernel space ID" >> log |
|
|
|
remove_chromeos_spaces |
|
$tpmc definespace 0x1007 0xa 0x8001 |
|
$tpmc definespace 0x1008 0xd 0x1 |
|
takeownership |
|
|
|
$ctr log |
|
} |
|
|
|
# Kernel space with wrong size |
|
test_wrong_size () { |
|
echo "TEST: bad kernel space size" >> log |
|
|
|
remove_chromeos_spaces |
|
$tpmc definespace 0x1007 0xa 0x8001 |
|
$tpmc definespace 0x1008 0xc 0x1 |
|
takeownership |
|
|
|
$ctr log |
|
} |
|
|
|
# Kernel space with wrong size AND bogus space to exhaust nvram |
|
test_wrong_size_hog () { |
|
echo "TEST: bad kernel space size and no room" >> log |
|
|
|
remove_chromeos_spaces |
|
$tpmc definespace 0x1007 0xa 0x8001 |
|
$tpmc definespace 0x1008 0x1 0x1 |
|
if [ "$test_kind" = "fake" ]; then |
|
space_hog_size=$(( $(cat nvram.freespace) - $space_overhead - 1 )) |
|
echo "remaining $(cat nvram.freespace) bytes" >> log |
|
else |
|
space_hog_size=$(( $(tpm-nvsize) - 2 )) |
|
fi |
|
echo "hogging $(( $space_hog_size )) bytes" >> log |
|
$tpmc definespace 0xcafe $(printf "0x%x" $space_hog_size) 0x1 \ |
|
|| echo "hogging failed!" >> log |
|
takeownership |
|
|
|
$ctr log |
|
} |
|
|
|
test_normal_run |
|
test_wrong_id |
|
test_wrong_size |
|
test_wrong_size_hog |
|
|
|
echo "test completed" >> log |
|
echo "test completed"
|
|
|