73 lines
3.3 KiB
Python
73 lines
3.3 KiB
Python
# 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 os, 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
|
|
caps_file='/sys/class/misc/tpm0/device/caps'
|
|
if not os.path.exists(caps_file):
|
|
caps_file='/sys/class/tpm/tpm0/device/caps'
|
|
try:
|
|
with open(caps_file, '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)
|
|
|
|
|