1# Copyright 2014 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""" 6Provides a utility function for working with TPM DAM logic. 7 8Dictionary Attack Mitigation (DAM) logic causes TPMs to enter a locked down 9state to defend against dictionary attacks. Authentication failures cause a 10counter to increment and when the counter exceeds some threshold, the defense 11mechanism is triggered. 12""" 13 14import os, re 15 16from autotest_lib.client.common_lib import utils 17from autotest_lib.client.cros import service_stopper 18 19def get_dictionary_attack_counter(): 20 """Returns the current dictionary attack counter.""" 21 tpm_command_info = { 22 '0x49465800': { # Infineon 23 'command': ('00 c1 ' # Tag = TPM_TAG_RQU_COMMAND 24 '00 00 00 16 ' # Size = 22 25 '00 00 00 65 ' # Ordinal = TPM_ORD_GetCapability 26 '00 00 00 10 ' # Capability Area = TPM_CAP_MFR 27 '00 00 00 04 ' # Size = 4 28 '00 00 08 02'), # Vendor-specific 29 'response_offset': 23}, # Vendor-specific 30 '0x57454300': { # Nuvoton 31 'command': ('00 c1 ' # Tag = TPM_TAG_RQU_COMMAND 32 '00 00 00 14 ' # Size = 20 33 '00 00 00 65 ' # Ordinal = TPM_ORD_GetCapability 34 '00 00 00 19 ' # Capability Area = TPM_CAP_DA_LOGIC 35 '00 00 00 02 ' # Size = 2 36 '00 04'), # Entity Type = TPM_ET_SRK 37 'response_offset': 18}, # TPM_DA_INFO.currentCount LSB 38 '0x53544d20': { # STMicro 39 'command': ('00 c1 ' # Tag = TPM_TAG_RQU_COMMAND 40 '00 00 00 14 ' # Size = 20 41 '00 00 00 65 ' # Ordinal = TPM_ORD_GetCapability 42 '00 00 00 19 ' # Capability Area = TPM_CAP_DA_LOGIC 43 '00 00 00 02 ' # Size = 2 44 '00 04'), # Entity Type = TPM_ET_SRK 45 'response_offset': 18}} # TPM_DA_INFO.currentCount LSB 46 caps_file='/sys/class/misc/tpm0/device/caps' 47 if not os.path.exists(caps_file): 48 caps_file='/sys/class/tpm/tpm0/device/caps' 49 try: 50 with open(caps_file, 'r') as fp: 51 caps = fp.read() 52 except IOError: 53 return 'Could not read TPM device caps.' 54 match = re.search(r'Manufacturer: (0x[0-9A-Fa-f]*)', caps) 55 if not match: 56 return 'Could not find TPM manufacturer.' 57 manufacturer = match.group(1) 58 if manufacturer not in tpm_command_info: 59 return 'TPM manufacturer not supported.' 60 with service_stopper.ServiceStopper(['cryptohomed', 61 'chapsd', 62 'tcsd']): 63 # The output of 'tpmc raw' is a series of bytes in the form 64 # '0x00 0x01 0x02 ...'. 65 tpm_response = utils.system_output( 66 'tpmc raw %s' % tpm_command_info[manufacturer]['command'], 67 ignore_status=True).split() 68 offset = tpm_command_info[manufacturer]['response_offset'] 69 if (len(tpm_response) <= offset): 70 return 'Unexpected TPM response (length = %d).' % len(tpm_response) 71 return int(tpm_response[offset], base=16) 72 73 74