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