blob: 6a765763c0e3e80cb42f18e46886f4d7ef902dc1 [file] [log] [blame]
# Copyright (c) 2012 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.
description "TrouSerS daemon"
author "chromium-os-dev@chromium.org"
# The TrouSerS daemon implements TSS, a standard API for access to
# TPM hardware (or to a TPM emulator).
#
# No 'start on'; the job is started with 'start' from tpm-probe.
stop on stopping boot-services
respawn
pre-start script
# If we're booting in recovery mode, first do a sanity check of the TPM and
# try to bring it to a sane state. Then clear the TPM owner and lock the
# TPM down.
if ! crossystem "recovery_reason?0" ; then
chromeos-tpm-recovery /var/log/tpm-recovery.log ||
logger -t "$UPSTART_JOB" "tpm-recovery status $?"
tpmc clear || logger -t "$UPSTART_JOB" "tpmc clear: status $?"
tpmc enable || logger -t "$UPSTART_JOB" "tpmc enable: status $?"
tpmc act || logger -t "$UPSTART_JOB" "tpmc act: status $?"
tpmc block || logger -t "$UPSTART_JOB" "tpmc block: status $?"
tpmc pplock || logger -t "$UPSTART_JOB" "tpmc pplock: status $?"
fi
if [ -e /sys/class/misc/tpm0/device/owned ]; then
owned=$(cat /sys/class/misc/tpm0/device/owned || echo "")
if [ "$owned" -eq "0" ]; then
# Clean up any existing tcsd state.
rm -rf /var/lib/tpm/*
elif [ "$owned" -eq "1" ]; then
# Already owned.
# Check if trousers' system.data is size zero. If so, then the TPM has
# been owned already and we need to copy over an empty system.data to be
# able to use it in trousers.
if [ ! -f /var/lib/tpm/system.data ] ||
[ ! -s /var/lib/tpm/system.data ]; then
if [ ! -e /var/lib/tpm ]; then
mkdir -m 0700 -p /var/lib/tpm
fi
umask 0177
cp --no-preserve=mode /etc/trousers/system.data.auth \
/var/lib/tpm/system.data
umask 0133
touch /var/lib/.tpm_owned
fi
fi
fi
# Check the dictionary-attack counter.
if grep -q "Manufacturer: 0x49465800" /sys/class/misc/tpm0/device/caps; then
# Infineon has a vendor-specific capability for this. The following command
# queries the TPM_CAP_MFR capability area.
tpm_command="00 c1 00 00 00 16 00 00 00 65 00 00 00 10 00 00 00 04 00 00 \
08 02"
# The output is vendor-specific; we're interested in the 24th byte. The
# output is printed in rows of 8 bytes so we want row 3, field 8.
count=$(($(tpmc raw $tpm_command | awk 'NR == 3 { print $8; }')))
elif [ -e /sys/class/misc/tpm0/device/caps ]; then
# If not Infineon, try to query the TPM_CAP_DA_LOGIC capability area with a
# TPM_ET_SRK entity type.
tpm_command="00 c1 00 00 00 14 00 00 00 65 00 00 00 19 00 00 00 02 00 04"
# The output is a TPM_DA_INFO structure; we're interested in the least
# significant byte of the currentCount field (row 3, field 3).
count=$(($(tpmc raw $tpm_command | awk 'NR == 3 { print $3; }')))
fi
if [ "$count" == "" ]; then
# Report 100 when we don't know the counter value.
count=100
fi
metrics_client -b -e Platform.TPM.DictionaryAttackCounter $count 100 ||
logger -t "$UPSTART_JOB" "metrics_client -e: status $?"
if [ $count -ne 0 ]; then
logger -t "$UPSTART_JOB" "WARNING: Non-zero dictionary attack counter found: $count"
metrics_client -b -v TPM.NonZeroDictionaryAttackCounter ||
logger -t "$UPSTART_JOB" "metrics_client -v: status $?"
fi
end script
expect fork
exec tcsd