344 lines
6.7 KiB
Bash
Executable File
344 lines
6.7 KiB
Bash
Executable File
#!/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 "%#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"
|