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