| # Copyright 2014 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import logging, os |
| |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.cros import cros_ui |
| |
| |
| _PASSWD_FILE = '/var/tmp/tpm_password' |
| _RM_DIRS = ('/home/.shadow/* ' + |
| '/home/chronos/.oobe_completed ' + |
| '/home/chronos/Local\ State ' + |
| '/var/cache/app_pack ' + |
| '/var/cache/shill/default.profile ' + |
| '/var/lib/tpm ' + |
| '/var/lib/whitelist/* ') |
| |
| |
| class NoTPMPasswordException(Exception): |
| """No TPM Password could be found.""" |
| pass |
| |
| |
| def TPMStatus(client): |
| """Returns a dictionary with TPM status. |
| |
| @param client: client object to run commands on. |
| """ |
| out = client.run('cryptohome --action=tpm_status').stdout.strip() |
| out = out.replace('TPM ', '') |
| lines = out.split('\n') |
| status = {} |
| for item in lines: |
| item = item.split(':') |
| if not item[0]: |
| continue |
| if len(item) == 1: |
| item.append('') |
| item = map(lambda x : x.strip(), item) |
| item[1] = True if item[1] == 'true' else item[1] |
| item[1] = False if item[1] == 'false' else item[1] |
| status[item[0]] = item[1] |
| return status |
| |
| |
| def IsTPMAvailable(client): |
| """Returns True if the TPM is unowned and enabled. |
| |
| @param client: client object to run commands on. |
| """ |
| status = TPMStatus(client) |
| return status['Enabled'] and not status['Owned'] |
| |
| |
| def ClearTPMServer(client, out_dir): |
| """Clears the TPM and reboots from a server-side autotest. |
| |
| @param client: client object to run commands on. |
| @param out_dir: temporary directory to store the retrieved password file. |
| """ |
| if IsTPMAvailable(client): |
| logging.debug('TPM is not owned') |
| return |
| |
| client.run('stop ui') |
| try: |
| password = TPMStatus(client)['Password'] |
| if not password: |
| try: |
| client.get_file(_PASSWD_FILE, out_dir) |
| except error.AutoservRunError: |
| raise NoTPMPasswordException( |
| 'TPM Password file %s doesn\'t exist, falling back on ' |
| 'clear_tpm_owner_request to clear the TPM. You may ' |
| 'need to have the firmware clear the TPM, for instance ' |
| 'by toggling the dev switch.' % _PASSWD_FILE) |
| with open(os.path.join(out_dir, |
| os.path.basename(_PASSWD_FILE))) as f: |
| password = f.read().rstrip() |
| if not password: |
| raise NoTPMPasswordException( |
| 'TPM Password file %s empty, falling back on ' |
| 'clear_tpm_owner_request to clear the TPM. You may need to ' |
| 'have the firmware clear the TPM, for instance by toggling ' |
| 'the dev switch.' % _PASSWD_FILE) |
| |
| res = client.run('tpm_clear --pass ' + password).stdout.strip() |
| logging.warn(repr(res)) |
| except NoTPMPasswordException as e: |
| logging.warn(e.args[0]) |
| client.run('crossystem clear_tpm_owner_request=1') |
| |
| CleanupAndReboot(client) |
| |
| |
| def ClearTPMOwnerRequest(client): |
| """Clears the TPM using crossystem command. |
| |
| @param client: client object to run commands on. |
| """ |
| if not client.run('crossystem clear_tpm_owner_request=1', |
| ignore_status=True).exit_status == 0: |
| raise error.TestFail('Unable to clear TPM.') |
| |
| CleanupAndReboot(client) |
| |
| |
| def CleanupAndReboot(client): |
| """Cleanup and reboot the device. |
| |
| @param client: client object to run commands on. |
| """ |
| cros_ui.stop_and_wait_for_chrome_to_exit() |
| |
| client.run('sudo rm -rf ' + _RM_DIRS, ignore_status=True) |
| client.run('sync', ignore_status=True) |
| client.reboot() |