• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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