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