• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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