1b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzato# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzato# Use of this source code is governed by a BSD-style license that can be
3b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzato# found in the LICENSE file.
4b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzato
5fae481d5329169bed279b579a85ba4873afca3d5Mike Trutyimport logging, re
6b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzatofrom autotest_lib.client.bin import test, utils
7b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzatofrom autotest_lib.client.common_lib import error
8fae481d5329169bed279b579a85ba4873afca3d5Mike Trutyfrom autotest_lib.client.cros import service_stopper
9fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
10fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
11fae481d5329169bed279b579a85ba4873afca3d5Mike Truty# Expected results of 'tpmc getX' commands.
12fae481d5329169bed279b579a85ba4873afca3d5Mike TrutyTPMC_EXPECTED = {
13fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    'getvf': # volatile (ST_CLEAR) flags
14fae481d5329169bed279b579a85ba4873afca3d5Mike Truty     set([('deactivated', '0'), ('physicalPresence', '0'),
15fae481d5329169bed279b579a85ba4873afca3d5Mike Truty          ('physicalPresenceLock', '1'), ('bGlobalLock', '1')]),
16fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    'getpf': # permanent flags
17fae481d5329169bed279b579a85ba4873afca3d5Mike Truty     set([('disable', '0'), ('ownership', '1'), ('deactivated', '0'),
18fae481d5329169bed279b579a85ba4873afca3d5Mike Truty          ('physicalPresenceHWEnable', '0'), ('physicalPresenceCMDEnable', '1'),
19fae481d5329169bed279b579a85ba4873afca3d5Mike Truty          ('physicalPresenceLifetimeLock', '1'), ('nvLocked', '1')])}
20fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
21b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzato
22c5bc881c1bef35b2e742014d34cee634d482df2cLuigi Semenzatodef missing_firmware_version():
23fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    """Check for empty fwid.
24fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
25fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    @return True if no fwid else False.
26fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    """
27fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    cmd = 'crossystem fwid'
28fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    return not utils.system_output(cmd, ignore_status=True).strip()
29fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
30fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
31fae481d5329169bed279b579a85ba4873afca3d5Mike Trutydef __run_tpmc_cmd(subcommand):
32fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    """Make this test more readable by simplifying commonly used tpmc command.
33fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
34fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    @param subcommand: String of the tpmc subcommand (getvf, getpf, getp, ...)
35fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    @return String output (which may be empty).
36fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    """
37fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    cmd = 'tpmc %s' % subcommand
38fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    return utils.system_output(cmd, ignore_status=True).strip()
39fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
40fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
41fae481d5329169bed279b579a85ba4873afca3d5Mike Trutydef check_tpmc(subcommand, expected):
42fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    """Runs tpmc command and checks the output against an expected result.
43fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
44fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    The expected results take 2 different forms:
45fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    1. A regular expression that is matched.
46fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    2. A set of tuples that are matched.
47fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
48fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    @param subcommand: String of the tpmc subcommand (getvf, getpf, getp, ...)
49fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    @param expected: Either a String re or the set of expected tuples.
50fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    @raises error.TestError() for invalidly matching expected.
51fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    """
52fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    error_msg = 'invalid response to tpmc %s' % subcommand
53fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    if isinstance(expected, str):
54fae481d5329169bed279b579a85ba4873afca3d5Mike Truty        out = __run_tpmc_cmd(subcommand)
55fae481d5329169bed279b579a85ba4873afca3d5Mike Truty        if (not re.match(expected, out)):
56fae481d5329169bed279b579a85ba4873afca3d5Mike Truty            raise error.TestError('%s: %s' % (error_msg, out))
57fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    else:
5877f06bcdf7e579f8cb1fd4a2ad030cc7b75b13ffMike Truty        result_set = utils.set_from_keyval_output(__run_tpmc_cmd(subcommand))
59fae481d5329169bed279b579a85ba4873afca3d5Mike Truty        if set(expected) <= result_set:
60fae481d5329169bed279b579a85ba4873afca3d5Mike Truty            return
61fae481d5329169bed279b579a85ba4873afca3d5Mike Truty        raise error.TestError('%s: expected=%s.' %
62fae481d5329169bed279b579a85ba4873afca3d5Mike Truty                              (error_msg, sorted(set(expected) - result_set)))
63fae481d5329169bed279b579a85ba4873afca3d5Mike Truty
64b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzato
65b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzatoclass hardware_TPMCheck(test.test):
66fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    """Check that the state of the TPM is as expected."""
67b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzato    version = 1
68b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzato
69b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzato
7098d1e54def96a88c70997f7882a384926297c043Alex Miller    def initialize(self):
7198d1e54def96a88c70997f7882a384926297c043Alex Miller        # Must stop the TCSD process to be able to collect TPM status,
7298d1e54def96a88c70997f7882a384926297c043Alex Miller        # then restart TCSD process to leave system in a known good state.
7398d1e54def96a88c70997f7882a384926297c043Alex Miller        # Must also stop services which depend on tcsd.
7498d1e54def96a88c70997f7882a384926297c043Alex Miller        self._services = service_stopper.ServiceStopper(['cryptohomed',
7598d1e54def96a88c70997f7882a384926297c043Alex Miller                                                         'chapsd', 'tcsd'])
7698d1e54def96a88c70997f7882a384926297c043Alex Miller        self._services.stop_services()
7798d1e54def96a88c70997f7882a384926297c043Alex Miller
7898d1e54def96a88c70997f7882a384926297c043Alex Miller
79fae481d5329169bed279b579a85ba4873afca3d5Mike Truty    def run_once(self):
80fae481d5329169bed279b579a85ba4873afca3d5Mike Truty        """Run a few TPM state checks."""
81c5bc881c1bef35b2e742014d34cee634d482df2cLuigi Semenzato        if missing_firmware_version():
82fae481d5329169bed279b579a85ba4873afca3d5Mike Truty            logging.warning('no firmware version, skipping test')
83b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzato            return
84b4b16e08b4a8613d3db01f4ed2b343f761bf02f0Luigi Semenzato
8598d1e54def96a88c70997f7882a384926297c043Alex Miller        # Check volatile and permanent flags
8698d1e54def96a88c70997f7882a384926297c043Alex Miller        for subcommand in ['getvf', 'getpf']:
8798d1e54def96a88c70997f7882a384926297c043Alex Miller            check_tpmc(subcommand, TPMC_EXPECTED[subcommand])
8898d1e54def96a88c70997f7882a384926297c043Alex Miller
8998d1e54def96a88c70997f7882a384926297c043Alex Miller        # Check space permissions
9098d1e54def96a88c70997f7882a384926297c043Alex Miller        check_tpmc('getp 0x1007', '.*0x8001')
9198d1e54def96a88c70997f7882a384926297c043Alex Miller        check_tpmc('getp 0x1008', '.*0x1')
9298d1e54def96a88c70997f7882a384926297c043Alex Miller
9398d1e54def96a88c70997f7882a384926297c043Alex Miller        # Check kernel space UID
9498d1e54def96a88c70997f7882a384926297c043Alex Miller        check_tpmc('read 0x1008 0x5', '.* 4c 57 52 47$')
9598d1e54def96a88c70997f7882a384926297c043Alex Miller
9698d1e54def96a88c70997f7882a384926297c043Alex Miller
9798d1e54def96a88c70997f7882a384926297c043Alex Miller    def cleanup(self):
9898d1e54def96a88c70997f7882a384926297c043Alex Miller        self._services.restore_services()
99