blob: e7638109efbde3584b3b4dee391a39e7f4686109 [file] [log] [blame]
#!/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=/usr/sbin/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"