xref: /aosp_15_r20/external/autotest/client/cros/tpm.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
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