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