Home | History | Annotate | Download | only in utility
      1 #!/bin/sh -u
      2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 #
      6 # Test the chromeos TPM recovery script by faking the entire execution
      7 # environment.
      8 
      9 rm -rf tpm-recovery-test-workdir
     10 mkdir  tpm-recovery-test-workdir
     11 cd     tpm-recovery-test-workdir
     12 
     13 test_kind=
     14 if [ $# -ge 1 ]; then
     15   test_kind="$1"
     16 fi
     17 
     18 if [ "$test_kind" != "" -a "$test_kind" != "fake" ]; then
     19   echo "$0: usage: $0 [fake]"
     20   echo "With fake as the argument, use a simulated TPM instead of the real one"
     21 fi
     22 
     23 if [ "$test_kind" = "fake" ]; then
     24   export USR_BIN=.
     25   export USR_SBIN=.
     26   export USR_LOCAL_BIN=.
     27   export USR_LOCAL_SBIN=.
     28   export DOT_RECOVERY=.recovery
     29   export ACPI_DIR=.
     30   ctr=../chromeos-tpm-recovery
     31   tpmc=./tpmc
     32 else
     33   ctr=chromeos-tpm-recovery
     34   tpmc=tpmc
     35 fi
     36 
     37 # For simplicity, build the permanent environment as if we prepared to run the
     38 # fake test, even if we're running the test on a real TPM.
     39 
     40 echo > .recovery
     41 echo 3 > BINF.0
     42 echo 0 > CHSW
     43 
     44 export NVRAM_SPACE_OVERHEAD=200
     45 space_overhead=$NVRAM_SPACE_OVERHEAD
     46 
     47 # build tpmc
     48 cat > tpmc <<"EOF"
     49 #!/bin/sh -u
     50 # Fake tpmc program
     51 
     52 definespace () {
     53   index=$2
     54   size=$3
     55   permissions=$4
     56   space_overhead=$NVRAM_SPACE_OVERHEAD
     57 
     58   if [ -e space.$index.data -a -e tpm-owned ]; then
     59     echo "cannot redefine space without auth"
     60   fi
     61 
     62   totalsize=$(( $size + $space_overhead ))
     63   free=$(cat nvram.freespace)
     64 
     65   if [ $totalsize -gt $free ]; then
     66     return 17  # NO_SPACE
     67   fi
     68 
     69   if [ $index != 0xf004 ]; then
     70     echo $size > space.$index.size
     71     echo $permissions > space.$index.perm
     72     for i in $(seq 1 $(($size))); do
     73       echo -n "ff " >> space.$index.data
     74     done
     75     echo $(( $free - $totalsize )) > nvram.freespace
     76   fi
     77   return 0
     78 }
     79 
     80 case $1 in
     81 
     82   clear)
     83     rm -f tpm-owned
     84   ;;
     85 
     86   enable)
     87     # boring
     88   ;;
     89 
     90   activate)
     91     # boring
     92   ;;
     93 
     94   definespace)
     95     definespace $*
     96   ;;
     97 
     98   getp)
     99     echo space blah has permissions $(cat space.$2.perm)
    100   ;;
    101 
    102   read)
    103     index=$2
    104     size=$3
    105     maxsize=$(cat space.$index.size)
    106     if [ $(($size > $maxsize)) -eq 1  ]; then
    107       echo "size $size too large for space (max is $maxsize)"
    108       exit 1
    109     fi
    110     dd if=space.$index.data bs=1 count=$(($3 * 3)) 2> /dev/null
    111   ;;
    112 
    113   write)
    114     args="$@"
    115     index=$2
    116     bytes="$(echo $args | sed 's/[^ ]* [^ ]* //')"
    117     size=$(echo $bytes | wc -w)
    118     maxsize=$(cat space.$index.size)
    119     if [ $(($size > $maxsize)) -eq 1  ]; then
    120       echo "size $size too large for space (max is $(($maxsize)))"
    121       exit 1
    122     fi
    123     re=$(echo "$bytes " | sed 's/././g')
    124     sed "s/$re/$bytes /" < space.$index.data > _tmp_
    125     mv _tmp_ space.$index.data
    126   ;;
    127 
    128   getpf)
    129     echo "disable 0"
    130     echo "deactivated 0"
    131     echo "nvLocked 1"
    132     echo "physicalPresenceLifetimeLock 1"
    133     echo "physicalPresenceHWEnable 0"
    134     echo "physicalPresenceCMDEnable 1"
    135   ;;
    136 
    137   getvf)
    138     echo "bGlobalLock 1"
    139     echo "physicalPresence 1"
    140     echo "physicalPresenceLock 0"
    141   ;;
    142 
    143   ppfin)
    144     # boring
    145   ;;
    146 
    147   ppon)
    148     # boring
    149   ;;
    150 
    151   *)
    152     echo "tpmc: invalid command $1"
    153     exit 1
    154   ;;
    155 esac
    156 
    157 EOF
    158 
    159 # build nvtool
    160 cat > tpm-nvtool <<"EOF"
    161 #!/bin/sh -u
    162 
    163 space_overhead=$NVRAM_SPACE_OVERHEAD
    164 
    165 print_space () {
    166   local index=$1
    167   printf "# NV Index 0x%08x" $(( $index ))
    168   echo " uninteresting random garbage"
    169   echo " further random garbage"
    170   echo ""
    171 }
    172 
    173 if [ "$1" = "--release" ]; then
    174   if [ "$2" != "--index" -o \
    175        "$4" != "--owner_password" ]; then
    176     echo "sorry, picky tpm-nvtool"
    177     exit 1
    178   fi
    179   index=$3
    180   if [ ! -f tpm-owned ]; then
    181     echo "tpm is unowned"
    182     exit 1
    183   fi
    184   size=$(cat space.$index.size)
    185   free=$(cat nvram.freespace)
    186   rm space.$index.*
    187   echo $(( $size + $space_overhead + $free )) > nvram.freespace
    188 elif [ "$1" = "--list" ]; then
    189   for s in space.*.data; do
    190     print_space $(echo $s | sed -e "s/[^.]*\.//" -e "s/\..*//")
    191   done
    192 fi
    193 EOF
    194 
    195 # build tpm_takeownership
    196 cat > tpm_takeownership <<"EOF"
    197 #!/bin/sh -u
    198 if [ -f tpm-owned ]; then
    199   echo "tpm is already owned"
    200   exit 1
    201 fi
    202 echo > tpm-owned
    203 EOF
    204 
    205 # build tcsd
    206 cat > tcsd <<"EOF"
    207 #!/bin/sh -u
    208 trap "{ rm tcsd_is_running; }" EXIT
    209 echo > tcsd_is_running
    210 sleep 365d
    211 EOF
    212 
    213 tcsd_pid=0
    214 
    215 start_tcsd () {
    216   if [ $tcsd_pid -ne 0 ]; then
    217     echo TCSD is already started
    218     exit 1
    219   fi
    220   tcsd -f &
    221   tcsd_pid=$!
    222   sleep 2
    223 }
    224 
    225 stop_tcsd () {
    226   if [ $tcsd_pid -eq 0 ]; then
    227     echo TCSD is already stopped
    228     exit 1
    229   fi
    230   kill $tcsd_pid
    231   sleep 0.5
    232   kill $tcsd_pid > /dev/null 2>&1
    233   sleep 0.5
    234   wait $tcsd_pid > /dev/null 2>&1  # we trust that tcsd will agree to die
    235   tcsd_pid=0
    236 }
    237 
    238 tpm_clear_and_reenable () {
    239   tpmc clear
    240   tpmc enable
    241   tpmc activate
    242 }
    243 
    244 takeownership () {
    245   if [ "$test_kind" = "fake" ]; then
    246     touch tpm_owned
    247   else
    248     tpm_clear_and_reenable
    249     start_tcsd
    250     tpm_takeownership -y -z
    251     stop_tcsd
    252   fi
    253 }
    254 
    255 remove_chromeos_spaces () {
    256   if [ "$test_kind" = "fake" ]; then
    257     rm -f space.*
    258     echo 1500 > nvram.freespace
    259   else
    260     takeownership
    261     start_tcsd
    262     tpm-nvtool --release --index 0x1007 --owner_password ""
    263     tpm-nvtool --release --index 0x1008 --owner_password ""
    264     stop_tcsd
    265     tpm_clear_and_reenable
    266   fi
    267 }
    268 
    269 chmod 755 tpmc tpm-nvtool tpm_takeownership tcsd
    270 
    271 echo "starting test, results in $(pwd)/log"
    272 echo "starting TPM recovery test" > log
    273 
    274 if ps ax | grep "tcs[d]"; then
    275   echo "a tcsd is process appears to be running, please kill it first"
    276   exit 1
    277 fi
    278 
    279 # normal run
    280 test_normal_run () {
    281   echo "TEST: normal run" >> log
    282 
    283   remove_chromeos_spaces
    284   $tpmc definespace 0x1007 0xa 0x8001
    285   $tpmc definespace 0x1008 0xd 0x1
    286   $tpmc write 0x1008 01 4c 57 52 47
    287   takeownership
    288 
    289   $ctr log
    290 }
    291 
    292 # Kernel space with wrong ID
    293 test_wrong_id () {
    294   echo "TEST: bad kernel space ID" >> log
    295 
    296   remove_chromeos_spaces
    297   $tpmc definespace 0x1007 0xa 0x8001
    298   $tpmc definespace 0x1008 0xd 0x1
    299   takeownership
    300 
    301   $ctr log
    302 }
    303 
    304 # Kernel space with wrong size
    305 test_wrong_size () {
    306   echo "TEST: bad kernel space size" >> log
    307 
    308   remove_chromeos_spaces
    309   $tpmc definespace 0x1007 0xa 0x8001
    310   $tpmc definespace 0x1008 0xc 0x1
    311   takeownership
    312 
    313   $ctr log
    314 }
    315 
    316 # Kernel space with wrong size AND bogus space to exhaust nvram
    317 test_wrong_size_hog () {
    318   echo "TEST: bad kernel space size and no room" >> log
    319 
    320   remove_chromeos_spaces
    321   $tpmc definespace 0x1007 0xa 0x8001
    322   $tpmc definespace 0x1008 0x1 0x1
    323   if [ "$test_kind" = "fake" ]; then
    324     space_hog_size=$(( $(cat nvram.freespace) - $space_overhead - 1 ))
    325     echo "remaining $(cat nvram.freespace) bytes" >> log
    326   else
    327     space_hog_size=$(( $(tpm-nvsize) - 2 ))
    328   fi
    329   echo "hogging $(( $space_hog_size )) bytes" >> log
    330   $tpmc definespace 0xcafe $(printf "0x%x" $space_hog_size) 0x1 \
    331     || echo "hogging failed!" >> log
    332   takeownership
    333 
    334   $ctr log
    335 }
    336 
    337 test_normal_run
    338 test_wrong_id
    339 test_wrong_size
    340 test_wrong_size_hog
    341 
    342 echo "test completed" >> log
    343 echo "test completed"
    344