blob: dfd04605603da66ce66c14d814b3c9a7cc159423 [file] [log] [blame]
# Copyright (c) 2013 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.
"""Verifies the TPM endorsement key.
This test (whether it succeeds or fails) always requests a TPM clear
on reboot. It works even if run multiple times without rebooting.
If the TPM is somehow owned but no password is available, the test
will fail but emit a reasonable error message (and it will pass on the
next boot).
"""
import logging
import tempfile
import unittest
import factory_common # pylint: disable=unused-import
from cros.factory.device import device_utils
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils import string_utils
class TPMVerifyEK(unittest.TestCase):
ARGS = [
# Chromebooks and Chromeboxes should set this to False.
Arg('is_cros_core', bool, 'Verify with ChromeOS Core endoresement',
default=False)
]
def setUp(self):
self.dut = device_utils.CreateDUTInterface()
def VerifyByCryptoHome(self):
"""Verifies TPM endorsement by CryptoHome service."""
def _TPMStatus():
"""Returns TPM status as a dictionary.
e.g., {'TPM Being Owned': 'false',
'TPM Ready': 'true',
'TPM Password': 'd641b63ce6ff',
'TPM Enabled': 'true',
'TPM Owned': 'true'}
"""
status_txt = self.dut.CheckOutput(['cryptohome', '--action=tpm_status'],
log=True)
status = string_utils.ParseDict(status_txt.splitlines())
logging.info('TPM status: %r', status)
return status
# Make sure TPM is enabled.
status = _TPMStatus()
self.assertEquals('true', status['TPM Enabled'])
# Check explicitly for the case where TPM is owned but password is
# unavailable. This shouldn't really ever happen, but in any case
# the TPM will become un-owned on reboot (thanks to the crossystem
# command above).
self.assertFalse(
status['TPM Owned'] == 'true' and not status['TPM Password'],
'TPM is owned but password is not available. Reboot and re-run.')
# Take ownership of the TPM (if not already taken).
self.dut.CheckCall(['cryptohome', '--action=tpm_take_ownership'],
log=True)
# Wait for TPM ownership to complete. No check_call=True since this
# may fail if the TPM is already owned.
self.dut.Call(['cryptohome', '--action=tpm_wait_ownership'],
log=True)
# Sync, to make sure TPM password was written to disk.
self.dut.CheckCall(['sync'], log=True)
self.assertEquals('true', _TPMStatus()['TPM Owned'])
# Verify the endorsement key.
with tempfile.TemporaryFile() as stderr:
self.dut.CheckCall(
['cryptohome', '--action=tpm_verify_ek'] + (
['--cros_core'] if self.args.is_cros_core else []),
log=True, stderr=stderr)
# Make sure there's no stderr from tpm_verify_ek (since that, plus
# check_call=True, is the only reliable way to make sure it
# worked).
stderr.seek(0)
self.assertEquals('', stderr.read())
def VerifyByTpmManager(self):
"""Verifies TPM endorsement by tpm-manager (from CryptoHome package)."""
# Take ownership of the TPM (if not already taken).
self.dut.CheckCall(['tpm-manager', 'initialize'], log=True)
# Verify TPM endorsement.
self.dut.CheckCall(['tpm-manager', 'verify_endorsement'] + (
['--cros_core'] if self.args.is_cros_core else []), log=True)
def runTest(self):
# Always clear TPM on next boot, in case any problems arise.
self.dut.CheckCall(['crossystem', 'clear_tpm_owner_request=1'], log=True)
# Check if we have tpm-manager in system.
if self.dut.Call(['which', 'tpm-manager']) == 0:
self.VerifyByTpmManager()
else:
self.VerifyByCryptoHome()