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 "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"
 |