• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2014 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.
4
5import logging, os
6
7from autotest_lib.client.common_lib import error
8from autotest_lib.client.cros import cros_ui
9
10
11_PASSWD_FILE = '/var/tmp/tpm_password'
12_RM_DIRS = ('/home/.shadow/* ' +
13            '/home/chronos/.oobe_completed ' +
14            '/home/chronos/Local\ State ' +
15            '/var/cache/app_pack ' +
16            '/var/cache/shill/default.profile ' +
17            '/var/lib/tpm ' +
18            '/var/lib/whitelist/* ')
19
20
21class NoTPMPasswordException(Exception):
22    """No TPM Password could be found."""
23    pass
24
25
26def TPMStatus(client):
27    """Returns a dictionary with TPM status.
28
29    @param client: client object to run commands on.
30    """
31    out = client.run('cryptohome --action=tpm_status').stdout.strip()
32    out = out.replace('TPM ', '')
33    lines = out.split('\n')
34    status = {}
35    for item in lines:
36        item = item.split(':')
37        if not item[0]:
38            continue
39        if len(item) == 1:
40            item.append('')
41        item = map(lambda x : x.strip(), item)
42        item[1] = True if item[1] == 'true' else item[1]
43        item[1] = False if item[1] == 'false' else item[1]
44        status[item[0]] = item[1]
45    return status
46
47
48def IsTPMAvailable(client):
49    """Returns True if the TPM is unowned and enabled.
50
51    @param client: client object to run commands on.
52    """
53    status = TPMStatus(client)
54    return status['Enabled'] and not status['Owned']
55
56
57def ClearTPMServer(client, out_dir):
58    """Clears the TPM and reboots from a server-side autotest.
59
60    @param client: client object to run commands on.
61    @param out_dir: temporary directory to store the retrieved password file.
62    """
63    if IsTPMAvailable(client):
64        logging.debug('TPM is not owned')
65        return
66
67    client.run('stop ui')
68    try:
69        password = TPMStatus(client)['Password']
70        if not password:
71            try:
72                client.get_file(_PASSWD_FILE, out_dir)
73            except error.AutoservRunError:
74                raise NoTPMPasswordException(
75                        'TPM Password file %s doesn\'t exist, falling back on '
76                        'clear_tpm_owner_request to clear the TPM. You may '
77                        'need to have the firmware clear the TPM, for instance '
78                        'by toggling the dev switch.' % _PASSWD_FILE)
79            with open(os.path.join(out_dir,
80                      os.path.basename(_PASSWD_FILE))) as f:
81                password = f.read().rstrip()
82        if not password:
83            raise NoTPMPasswordException(
84                    'TPM Password file %s empty, falling back on '
85                    'clear_tpm_owner_request to clear the TPM. You may need to '
86                    'have the firmware clear the TPM, for instance by toggling '
87                    'the dev switch.' % _PASSWD_FILE)
88
89        res = client.run('tpm_clear --pass ' + password).stdout.strip()
90        logging.warn(repr(res))
91    except NoTPMPasswordException as e:
92        logging.warn(e.args[0])
93        client.run('crossystem clear_tpm_owner_request=1')
94
95    CleanupAndReboot(client)
96
97
98def ClearTPMOwnerRequest(client):
99    """Clears the TPM using crossystem command.
100
101    @param client: client object to run commands on.
102    """
103    if not client.run('crossystem clear_tpm_owner_request=1',
104                      ignore_status=True).exit_status == 0:
105        raise error.TestFail('Unable to clear TPM.')
106
107    CleanupAndReboot(client)
108
109
110def CleanupAndReboot(client):
111    """Cleanup and reboot the device.
112
113    @param client: client object to run commands on.
114    """
115    cros_ui.stop_and_wait_for_chrome_to_exit()
116
117    client.run('sudo rm -rf ' + _RM_DIRS, ignore_status=True)
118    client.run('sync', ignore_status=True)
119    client.reboot()
120