| # 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) |
| |
| |