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 5 import logging, os 6 7 from autotest_lib.client.common_lib import error 8 from 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 21 class NoTPMPasswordException(Exception): 22 """No TPM Password could be found.""" 23 pass 24 25 26 def 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 48 def 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 57 def 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 98 def 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 110 def 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