Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: tpm_handler.py

Issue 3781016: Introduce SAFT TPM testing support. (Closed) Base URL: http://git.chromium.org/git/saft.git
Patch Set: Addressed review comments. Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « test_tpm_handler.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 '''A module containing TPM handler class used by SAFT.'''
7 import os
8 import re
9 import shutil
10
11 FW_NV_ADDRESS = 0x1007
12 KERNEL_NV_ADDRESS = 0x1008
13 COMMENT_PATTERN = '#saft'
14
15 class TpmError(Exception):
16 pass
17
18 class TpmNvRam(object):
19 '''An object representing TPM NvRam.
20
21 Attributes:
22 addr: a number, NvRAm address in TPM.
23 size: a number, count of bites in this NvRam section.
24 os_if: an instance of the OS interface (chromeos_interface or a mock
25 object).
26 version_offset: - a number, offset into the NvRam contents where the the
27 versions are stored. The total version field size is 4 bytes, the
28 first two bytes are the body version, the second two bytes are the key
29 version. Numbers are stored in little endian format.
30 pattern: optional, a tuple of two elements, the first element is the
31 offset of the pattern expected to be present in the NvRam, and the
32 second element is an array of bytes the pattern must match.
33 contents: an array of bytes, the contents of the NvRam.
34 '''
35
36 def __init__(self, addr, size, version_offset, data_pattern=None):
37 self.addr = addr
38 self.size = size
39 self.os_if = None
40 self.version_offset = version_offset
41 self.pattern = data_pattern
42 self.contents = []
43
44 def init(self, os_if):
45 self.os_if = os_if
46 cmd = 'tpmc read 0x%x 0x%x' % (self.addr, self.size)
47 nvram_data = self.os_if.run_shell_command_get_output(cmd)[0].split()
48 self.contents = [int(x, 16) for x in nvram_data]
49 if self.pattern:
50 pattern_offset = self.pattern[0]
51 pattern_data = self.pattern[1]
52 contents_pattern = self.contents[pattern_offset:pattern_offset +
53 len(pattern_data)]
54 if contents_pattern != pattern_data:
55 raise TpmError('Nvram pattern does not match')
56
57 def get_body_version(self):
58 return self.contents[
59 self.version_offset + 1] * 256 + self.contents[self.version_offset]
60
61 def get_key_version(self):
62 return self.contents[
63 self.version_offset + 3] * 256 + self.contents[
64 self.version_offset + 2]
65
66 def set_body_version(self, new_version):
67 new_contents = list(self.contents)
68 new_contents[self.version_offset + 1] = (new_version >> 8) & 0xff
69 new_contents[self.version_offset] = new_version & 0xff
70 if new_contents != self.contents:
71 self.contents = new_contents
72 cmd = 'tpmc write 0x%x %s' % (
73 self.addr, ' '.join('0x%2.2x' % x for x in new_contents))
74 self.os_if.run_shell_command(cmd)
75 else:
76 self.os_if.log('no version change for 0x%x' % self.addr)
77
78 class TpmHandler(object):
79 '''An object to control TPM device's NVRAM.
80
81 Attributes:
82 cros_if: an instance of the OS interface (chromeos_interface or a mock
83 object).
84 nvrams: A dictionary where the keys are the nvram names, and the values
85 are instances of TpmNvRam objects, providing access to the
86 appropriate TPM NvRam sections.
87 '''
88
89 def __init__(self):
90 self.cros_if = None
91 self.nvrams = {
92 'kernel': TpmNvRam(KERNEL_NV_ADDRESS, 13, 5, (
93 1, [0x4c, 0x57, 0x52, 0x47])),
94 'bios': TpmNvRam(FW_NV_ADDRESS, 10, 2)
95 }
96
97 def init(self, cros_if):
98 self.cros_if = cros_if
99 status = self.cros_if.run_shell_command_get_output(
100 'initctl status tcsd')[0]
101 if status.startswith('tcsd start/running'):
102 self.cros_if.run_shell_command('stop tcsd')
103
104 for nvram in self.nvrams.itervalues():
105 nvram.init(self.cros_if)
106
107 def get_fw_version(self):
108 return self.nvrams['bios'].get_body_version()
109
110 def get_kernel_version(self):
111 return self.nvrams['kernel'].get_body_version()
112
113 def set_kernel_version(self, new_version):
114 return self.nvrams['kernel'].set_body_version(new_version)
115
116 def _version_good(self, nvram, version_a, version_b):
117 return self.nvrams[nvram].get_body_version() == max(
118 version_a, version_b)
119
120 def kernel_version_good(self, version_a, version_b):
121 return self._version_good('kernel', version_a, version_b)
122
123 def fw_version_good(self, version_a, version_b):
124 return self._version_good('bios', version_a, version_b)
125
126 def enable_write_access(self, config_file_name='/etc/init/tcsd.conf'):
127 '''Enable TPM write access on the next recovery mode restart.
128
129 Comment out from the TPM upstart script the following lines locking
130 the TPM (and thus preventing write access):
131
132 tpmc block || logger "tpmc block: status $?"
133 tpmc pplock || logger "tpmc pplock: status $?"
134
135 Save the original file in the state directory for future recovery.
136 '''
137
138 pattern = re.compile('^\s+tpmc\s+(b|pp)lock\s+\|\|')
139 new_file_name = self.cros_if.state_dir_file(
140 os.path.basename(config_file_name))
141 shutil.copyfile(config_file_name, new_file_name + '.bak')
142 config_file = open(config_file_name, 'r')
143 new_file = open(new_file_name, 'w')
144 for line in config_file.readlines():
145 if pattern.search(line):
146 new_file.write('%s%s' % (COMMENT_PATTERN, line))
147 else:
148 new_file.write(line)
149 new_file.close()
150 config_file.close()
151 shutil.move(new_file_name, config_file_name)
152
153 def disable_write_access(self, config_file_name='/etc/init/tcsd.conf'):
154 '''Disable TPM write access.
155
156 Restore previously edited startup file to lock the TPM on the next
157 restart.
158 '''
159 backup_file_name = self.cros_if.state_dir_file(
160 os.path.basename(config_file_name) + '.bak')
161 shutil.move(backup_file_name, config_file_name)
OLDNEW
« no previous file with comments | « test_tpm_handler.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698