1# Copyright (c) 2021 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"""Utilities to interact with the TPM on a CrOS device.""" 6 7import logging 8import re 9 10import common 11 12from autotest_lib.client.bin import utils 13from autotest_lib.client.common_lib import error 14 15CRYPTOHOME_CMD = '/usr/sbin/cryptohome' 16UNAVAILABLE_ACTION = 'Unknown action or no action given.' 17TPM_MANAGER_CMD = '/usr/bin/tpm_manager_client' 18 19 20class ChromiumOSError(error.TestError): 21 """Generic error for ChromiumOS-specific exceptions.""" 22 23 pass 24 25 26def get_tpm_status(): 27 """Get the TPM status. 28 29 Returns: 30 A TPM status dictionary, for example: 31 { 'Enabled': True, 32 'Owned': True, 33 'Ready': True 34 } 35 """ 36 out = run_cmd(TPM_MANAGER_CMD + ' status') 37 status = {} 38 for field in ['enabled', 'owned']: 39 match = re.search('%s: (true|false)' % field, out) 40 if not match: 41 raise ChromiumOSError('Invalid TPM status: "%s".' % out) 42 status[field] = match.group(1) == 'true' 43 status['Enabled'] = status['enabled'] 44 status['Owned'] = status['owned'] 45 status['Ready'] = status['enabled'] and status['owned'] 46 return status 47 48 49def get_tpm_da_info(): 50 """Get the TPM dictionary attack information. 51 Returns: 52 A TPM dictionary attack status dictionary, for example: 53 { 54 'dictionary_attack_counter': 0, 55 'dictionary_attack_threshold': 200, 56 'dictionary_attack_lockout_in_effect': False, 57 'dictionary_attack_lockout_seconds_remaining': 0 58 } 59 """ 60 status = {} 61 out = run_cmd(TPM_MANAGER_CMD + ' get_da_info') 62 for line in out.splitlines()[1:-1]: 63 items = line.strip().split(':') 64 if len(items) != 2: 65 continue 66 if items[1].strip() == 'false': 67 value = False 68 elif items[1].strip() == 'true': 69 value = True 70 elif items[1].split('(')[0].strip().isdigit(): 71 value = int(items[1].split('(')[0].strip()) 72 else: 73 value = items[1].strip(' "') 74 status[items[0].strip()] = value 75 return status 76 77 78 79def run_cmd(cmd): 80 """Run a command on utils.system_output, and append '2>&1'.""" 81 return utils.system_output(cmd + ' 2>&1', retain_output=True, 82 ignore_status=True).strip() 83