1c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# Use of this source code is governed by a BSD-style license that can be 3c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# found in the LICENSE file. 4c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 5be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam"""A module containing TPM handler class used by SAFT.""" 6c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 7c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong TamFW_NV_ADDRESS = 0x1007 8c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong TamKERNEL_NV_ADDRESS = 0x1008 9c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 10c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass TpmError(Exception): 11c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pass 12c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 13c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass TpmNvRam(object): 14be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """An object representing TPM NvRam. 15c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 16c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Attributes: 17c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam addr: a number, NvRAm address in TPM. 18c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam size: a number, count of bites in this NvRam section. 19ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam os_if: an instance of the OS interface (os_interface or a mock object). 20c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam version_offset: - a number, offset into the NvRam contents where the the 21c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam versions are stored. The total version field size is 4 bytes, the 22c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam first two bytes are the body version, the second two bytes are the key 23c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam version. Numbers are stored in little endian format. 24c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pattern: optional, a tuple of two elements, the first element is the 25c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam offset of the pattern expected to be present in the NvRam, and the 26c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam second element is an array of bytes the pattern must match. 27c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam contents: an array of bytes, the contents of the NvRam. 28be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 29c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 30c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def __init__(self, addr, size, version_offset, data_pattern=None): 31c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.addr = addr 32c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.size = size 33c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.os_if = None 34c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.version_offset = version_offset 35c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.pattern = data_pattern 36c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.contents = [] 37c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 38c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def init(self, os_if): 39c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.os_if = os_if 40c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam cmd = 'tpmc read 0x%x 0x%x' % (self.addr, self.size) 41c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam nvram_data = self.os_if.run_shell_command_get_output(cmd)[0].split() 42c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.contents = [int(x, 16) for x in nvram_data] 43c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if self.pattern: 44c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pattern_offset = self.pattern[0] 45c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pattern_data = self.pattern[1] 46c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam contents_pattern = self.contents[pattern_offset:pattern_offset + 47c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam len(pattern_data)] 48c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if contents_pattern != pattern_data: 49c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise TpmError('Nvram pattern does not match') 50c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 51c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_body_version(self): 52c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return self.contents[ 53c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.version_offset + 1] * 256 + self.contents[self.version_offset] 54c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 55c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_key_version(self): 56c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return self.contents[ 57c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.version_offset + 3] * 256 + self.contents[ 58c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.version_offset + 2] 59c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 60c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass TpmHandler(object): 61be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """An object to control TPM device's NVRAM. 62c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 63c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Attributes: 64ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam os_if: an instance of the OS interface (os_interface or a mock object). 65c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam nvrams: A dictionary where the keys are the nvram names, and the values 66c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam are instances of TpmNvRam objects, providing access to the 67c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam appropriate TPM NvRam sections. 68be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 69c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 70c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def __init__(self): 71ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam self.os_if = None 72c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.nvrams = { 73c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'kernel': TpmNvRam(KERNEL_NV_ADDRESS, 13, 5, ( 74c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 1, [0x4c, 0x57, 0x52, 0x47])), 75c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'bios': TpmNvRam(FW_NV_ADDRESS, 10, 2) 76c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam } 77d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.trunksd_started = False 78d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.tcsd_started = False 79c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 80ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam def init(self, os_if): 81ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam self.os_if = os_if 82d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.stop_daemon() 83c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for nvram in self.nvrams.itervalues(): 84ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam nvram.init(self.os_if) 85d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.restart_daemon() 8648d92dcbae5b30b14bb7af84652af7a8b0eb8612Wai-Hong Tam 87c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_fw_version(self): 88c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return self.nvrams['bios'].get_body_version() 89c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 9073d6adec5d387c330b85c4fd7e0473c84f651435Wai-Hong Tam def get_fw_key_version(self): 91a4f655312719707e3df448bc5ff4e28eab9d388fChun-ting Chang return self.nvrams['bios'].get_key_version() 92a4f655312719707e3df448bc5ff4e28eab9d388fChun-ting Chang 93c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_kernel_version(self): 94c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return self.nvrams['kernel'].get_body_version() 9573d6adec5d387c330b85c4fd7e0473c84f651435Wai-Hong Tam 9673d6adec5d387c330b85c4fd7e0473c84f651435Wai-Hong Tam def get_kernel_key_version(self): 9773d6adec5d387c330b85c4fd7e0473c84f651435Wai-Hong Tam return self.nvrams['kernel'].get_key_version() 98d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam 99d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam def stop_daemon(self): 100d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam """Stop TPM related daemon.""" 101d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam if self.trunksd_started or self.tcsd_started: 102d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam raise TpmError('Called stop_daemon() before') 103d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam 104d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam cmd = 'initctl status tcsd || initctl status trunksd' 105d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam status = self.os_if.run_shell_command_get_output(cmd) or [''] 106d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam # Expected status is like ['trunksd start/running, process 2375'] 107d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.trunksd_started = status[0].startswith('trunksd start/running') 108d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam if self.trunksd_started: 109d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.os_if.run_shell_command('stop trunksd') 110d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam else: 111d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.tcsd_started = status[0].startswith('tcsd start/running') 112d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam if self.tcsd_started: 113d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.os_if.run_shell_command('stop tcsd') 114d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam 115d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam def restart_daemon(self): 116d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam """Restart TPM related daemon which was stopped by stop_daemon().""" 117d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam if self.trunksd_started: 118d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.os_if.run_shell_command('start trunksd') 119d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.trunksd_started = False 120d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam elif self.tcsd_started: 121d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.os_if.run_shell_command('start tcsd') 122d2eaa3f3af3f86aa7df0aed3726a0bff8ca526a2Wai-Hong Tam self.tcsd_started = False 123