blob: 0c7666e2c0cee522fc89d7df4455e3161c2f20c4 [file] [log] [blame]
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Provides a utility function for working with TPM DAM logic.
Dictionary Attack Mitigation (DAM) logic causes TPMs to enter a locked down
state to defend against dictionary attacks. Authentication failures cause a
counter to increment and when the counter exceeds some threshold, the defense
mechanism is triggered.
"""
import re
from autotest_lib.client.common_lib import utils
from autotest_lib.client.cros import service_stopper
def get_dictionary_attack_counter():
"""Returns the current dictionary attack counter."""
tpm_command_info = {
'0x49465800': { # Infineon
'command': ('00 c1 ' # Tag = TPM_TAG_RQU_COMMAND
'00 00 00 16 ' # Size = 22
'00 00 00 65 ' # Ordinal = TPM_ORD_GetCapability
'00 00 00 10 ' # Capability Area = TPM_CAP_MFR
'00 00 00 04 ' # Size = 4
'00 00 08 02'), # Vendor-specific
'response_offset': 23}, # Vendor-specific
'0x57454300': { # Nuvoton
'command': ('00 c1 ' # Tag = TPM_TAG_RQU_COMMAND
'00 00 00 14 ' # Size = 20
'00 00 00 65 ' # Ordinal = TPM_ORD_GetCapability
'00 00 00 19 ' # Capability Area = TPM_CAP_DA_LOGIC
'00 00 00 02 ' # Size = 2
'00 04'), # Entity Type = TPM_ET_SRK
'response_offset': 18}, # TPM_DA_INFO.currentCount LSB
'0x53544d20': { # STMicro
'command': ('00 c1 ' # Tag = TPM_TAG_RQU_COMMAND
'00 00 00 14 ' # Size = 20
'00 00 00 65 ' # Ordinal = TPM_ORD_GetCapability
'00 00 00 19 ' # Capability Area = TPM_CAP_DA_LOGIC
'00 00 00 02 ' # Size = 2
'00 04'), # Entity Type = TPM_ET_SRK
'response_offset': 18}} # TPM_DA_INFO.currentCount LSB
try:
with open('/sys/class/misc/tpm0/device/caps', 'r') as fp:
caps = fp.read()
except IOError:
return 'Could not read TPM device caps.'
match = re.search(r'Manufacturer: (0x[0-9A-Fa-f]*)', caps)
if not match:
return 'Could not find TPM manufacturer.'
manufacturer = match.group(1)
if manufacturer not in tpm_command_info:
return 'TPM manufacturer not supported.'
with service_stopper.ServiceStopper(['cryptohomed',
'chapsd',
'tcsd']):
# The output of 'tpmc raw' is a series of bytes in the form
# '0x00 0x01 0x02 ...'.
tpm_response = utils.system_output(
'tpmc raw %s' % tpm_command_info[manufacturer]['command'],
ignore_status=True).split()
offset = tpm_command_info[manufacturer]['response_offset']
if (len(tpm_response) <= offset):
return 'Unexpected TPM response (length = %d).' % len(tpm_response)
return int(tpm_response[offset], base=16)