1# Copyright 2018 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. 4import logging 5 6from autotest_lib.client.common_lib import error 7from autotest_lib.client.common_lib.cros import cr50_utils 8from autotest_lib.server.cros.faft.cr50_test import Cr50Test 9 10 11class firmware_Cr50TpmMode(Cr50Test): 12 """Verify TPM disabling and getting back enabled after reset. 13 14 Attributes: 15 can_set_tpm: True if board property has 'BOARD_ALLOW_CHANGE_TPM_MODE'. 16 False, otherwise. 17 """ 18 version = 1 19 20 def initialize(self, host, cmdline_args, full_args): 21 super(firmware_Cr50TpmMode, self).initialize(host, cmdline_args, 22 full_args) 23 24 self.can_set_tpm = self.cr50.uses_board_property( 25 'BOARD_ALLOW_CHANGE_TPM_MODE') 26 27 def init_tpm_mode(self): 28 """Reset the device.""" 29 if self.can_set_tpm: 30 logging.info('Reset') 31 self.servo.get_power_state_controller().reset() 32 self.switcher.wait_for_client() 33 34 def cleanup(self): 35 """Initialize TPM mode by resetting CR50""" 36 try: 37 self.init_tpm_mode() 38 finally: 39 super(firmware_Cr50TpmMode, self).cleanup() 40 41 def get_tpm_mode(self, long_opt): 42 """Query the current TPM mode. 43 44 Args: 45 long_opt: Boolean to decide whether to use long opt 46 for gsctool command. 47 """ 48 opt_text = '--tpm_mode' if long_opt else '-m' 49 return cr50_utils.GSCTool(self.host, ['-a', opt_text]).stdout.strip() 50 51 def set_tpm_mode(self, disable_tpm, long_opt): 52 """Disable or Enable TPM mode. 53 54 Args: 55 disable_tpm: Disable TPM if True. 56 Enable (or Confirm Enabling) otherwise. 57 long_opt: Boolean to decide whether to use long opt 58 for gsctool command. 59 60 """ 61 mode_param = 'disable' if disable_tpm else 'enable' 62 opt_text = '--tpm_mode' if long_opt else '-m' 63 return cr50_utils.GSCTool(self.host, 64 ['-a', opt_text, mode_param]).stdout.strip() 65 66 def run_test_tpm_mode(self, disable_tpm, long_opt): 67 """Run a test for the case of either disabling TPM or enabling. 68 69 Args: 70 disable_tpm: Disable TPM if True. Enable TPM otherwise. 71 long_opt: Boolean to decide whether to use long opt 72 for gsctool command. 73 74 Raises: 75 TestFail: If test fails for unexpected TPM mode change. 76 """ 77 self.init_tpm_mode() 78 79 # Check if TPM is enabled through console command. 80 logging.info('Get TPM Mode') 81 if not self.cr50.tpm_is_enabled(): 82 raise error.TestFail('TPM is not enabled after reset,') 83 84 # Check if Key Ladder is enabled. 85 if self.cr50.keyladder_is_disabled(): 86 raise error.TestFail('Failed to restore H1 Key Ladder') 87 88 # Check if TPM is enabled through gsctool. 89 output_log = self.get_tpm_mode(long_opt) 90 logging.info(output_log) 91 if not 'enabled (0)' in output_log.lower(): 92 raise error.TestFail('Failed to read TPM mode after reset') 93 94 # Check if CR50 responds to a TPM request. 95 if self.tpm_is_responsive(): 96 logging.info('Checked TPM response') 97 else: 98 raise error.TestFail('Failed to check TPM response') 99 100 # Change TPM Mode 101 logging.info('Set TPM Mode') 102 103 if self.can_set_tpm: 104 output_log = self.set_tpm_mode(disable_tpm, long_opt) 105 logging.info(output_log) 106 else: 107 try: 108 output_log = self.set_tpm_mode(disable_tpm, long_opt) 109 except error.AutoservRunError as e: 110 logging.info('Failed to set TPM mode as expected') 111 logging.info(str(e)) 112 else: 113 raise error.TestFail('Setting TPM mode should not be allowed') 114 finally: 115 logging.info(output_log) 116 return 117 118 # Check the result of TPM Mode. 119 if disable_tpm: 120 if not 'disabled (2)' in output_log.lower(): 121 raise error.TestFail('Failed to disable TPM: %s' % output_log) 122 123 # Check if TPM is disabled. The run should fail. 124 if self.tpm_is_responsive(): 125 raise error.TestFail('TPM responded') 126 else: 127 logging.info('TPM did not respond') 128 129 if not self.cr50.keyladder_is_disabled(): 130 raise error.TestFail('Failed to revoke H1 Key Ladder') 131 else: 132 if not 'enabled (1)' in output_log.lower(): 133 raise error.TestFail('Failed to enable TPM: %s' % output_log) 134 135 # Check if TPM is enabled still. 136 if self.tpm_is_responsive(): 137 logging.info('Checked TPM response') 138 else: 139 raise error.TestFail('Failed to check TPM response') 140 141 # Subsequent set-TPM-mode vendor command should fail. 142 try: 143 output_log = self.set_tpm_mode(not disable_tpm, long_opt) 144 except error.AutoservRunError: 145 logging.info('Expectedly failed to disable TPM mode'); 146 else: 147 raise error.TestFail('Unexpected result in disabling TPM mode:' 148 ' %s' % output_log) 149 150 def run_once(self): 151 """Test Disabling TPM and Enabling TPM""" 152 long_opts = [True, False] 153 154 # One iteration runs with the short opt '-m', 155 # and the other runs with the long opt '--tpm_mode' 156 for long_opt in long_opts: 157 # Test 1. Disabling TPM 158 logging.info('Disabling TPM') 159 self.run_test_tpm_mode(True, long_opt) 160 161 # Test 2. Enabling TPM 162 logging.info('Enabling TPM') 163 self.run_test_tpm_mode(False, long_opt) 164