• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Use of this source code is governed by a BSD-style license that can be
2# found in the LICENSE file.
3
4import hashlib
5
6from autotest_lib.client.common_lib import error
7from autotest_lib.client.common_lib.cros import g2f_utils
8from autotest_lib.client.common_lib.cros import tpm_utils
9from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
10
11U2F_AUTH_ENFORCE=3
12
13class firmware_Cr50U2fPowerwash(FirmwareTest):
14    """
15    A test that runs sanity checks for U2F register and authenticate functions,
16    and checks that key handles are invalidated after TPM clear.
17    """
18    version = 1
19
20    def _safe_power_short_press(self):
21        """Stop powerd before pressing the power button."""
22        # Validating U2F requires pressing the power button. If those power button
23        # presses power off the AP, stop powerd before the test to ignore them.
24        if self.faft_config.ec_forwards_short_pp_press:
25            self.stop_powerd()
26        self.servo.power_short_press()
27
28    def parse_g2ftool_output(self, stdout):
29        """Parses the key-value pairs returned by g2ftool
30
31        @param stdout: g2ftool output.
32        """
33        return dict((k, v)
34                    for k,v in (line.split('=')
35                                for line in stdout.strip().split('\n')))
36
37    def run_once(self, host=None):
38        """Tests that U2F keys are invalidated by powerwash."""
39        self.client = host
40
41        # Start by clearing TPM to make sure the device is in a known state.
42        tpm_utils.ClearTPMOwnerRequest(self.client, wait_for_ready=True)
43
44        # u2fd reads files from the user's home dir, so we need to log in.
45        g2f_utils.ChromeOSLogin(self.client);
46
47        # U2fd does will not start normally if the device has not gone
48        # through OOBE. Force it to startup.
49        cr50_dev = g2f_utils.StartU2fd(self.client)
50
51        # Register requires physical presence.
52        self._safe_power_short_press()
53
54        # Register to create a new key handle.
55        g2f_reg = g2f_utils.G2fRegister(
56            self.client,
57            cr50_dev,
58            hashlib.sha256('test_challenge').hexdigest(),
59            hashlib.sha256('test_application').hexdigest(),
60            U2F_AUTH_ENFORCE)
61
62        # Sanity check that we managed to register.
63        if not g2f_reg.exit_status == 0:
64          raise error.TestError('Register failed.')
65
66        # Extract newly created key handle.
67        key_handle = self.parse_g2ftool_output(g2f_reg.stdout)['key_handle']
68
69        # Auth requires physical presence.
70        self._safe_power_short_press()
71
72        # Sanity check that we can authenticate with the new key handle.
73        g2f_auth = g2f_utils.G2fAuth(
74            self.client,
75            cr50_dev,
76            hashlib.sha256('test_challenge').hexdigest(),
77            hashlib.sha256('test_application').hexdigest(),
78            key_handle,
79            U2F_AUTH_ENFORCE)
80
81        if not g2f_auth.exit_status == 0:
82          raise error.TestError('Authenticate failed.')
83
84        # Clear TPM. We should no longer be able to authenticate with the
85        # key handle after this.
86        tpm_utils.ClearTPMOwnerRequest(self.client, wait_for_ready=True)
87
88        # u2fd reads files from the user's home dir, so we need to log in.
89        g2f_utils.ChromeOSLogin(self.client)
90
91        # U2fd does will not start normally if the device has not gone
92        # through OOBE. Force it to startup.
93        cr50_dev = g2f_utils.StartU2fd(self.client)
94
95        # Check the key handle is no longer valid.
96        self._safe_power_short_press()
97        g2f_auth_clear = g2f_utils.G2fAuth(
98            self.client,
99            cr50_dev,
100            hashlib.sha256('test_challenge').hexdigest(),
101            hashlib.sha256('test_application').hexdigest(),
102            key_handle,
103            U2F_AUTH_ENFORCE)
104
105        if g2f_auth_clear.exit_status == 0:
106          raise error.TestError('Authenticate succeeded; should have failed')
107
108
109    def cleanup(self):
110        """Leave the device in a predictable state"""
111        g2f_utils.ChromeOSLogout(self.client)
112
113        super(firmware_Cr50U2fPowerwash, self).cleanup()
114