xref: /aosp_15_r20/external/autotest/server/site_tests/firmware_Cr50TpmMode/firmware_Cr50TpmMode.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
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