xref: /aosp_15_r20/external/autotest/client/common_lib/smogcheck_tpm.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li# Lint as: python2, python3
2*9c5db199SXin Li# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
3*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be
4*9c5db199SXin Li# found in the LICENSE file.
5*9c5db199SXin Li
6*9c5db199SXin Li"""A Python library to interact with TPM module for testing.
7*9c5db199SXin Li
8*9c5db199SXin LiBackground
9*9c5db199SXin Li - TPM stands for Trusted Platform Module, a piece of security device
10*9c5db199SXin Li - TPM specification is the work of Trusted Computing Group
11*9c5db199SXin Li - As of September 2011, the current TPM specification is version 1.2
12*9c5db199SXin Li
13*9c5db199SXin LiDependency
14*9c5db199SXin Li - This library depends on a C shared library called "libtspi.so", which
15*9c5db199SXin Li   contains a set of APIs for interacting with TPM module
16*9c5db199SXin Li
17*9c5db199SXin LiNotes:
18*9c5db199SXin Li - An exception is raised if it doesn't make logical sense to continue program
19*9c5db199SXin Li   flow (e.g. I/O error prevents test case from executing)
20*9c5db199SXin Li - An exception is caught and then converted to an error code if the caller
21*9c5db199SXin Li   expects to check for error code per API definition
22*9c5db199SXin Li"""
23*9c5db199SXin Li
24*9c5db199SXin Lifrom __future__ import absolute_import
25*9c5db199SXin Lifrom __future__ import division
26*9c5db199SXin Lifrom __future__ import print_function
27*9c5db199SXin Li
28*9c5db199SXin Liimport datetime, logging
29*9c5db199SXin Lifrom six.moves import range
30*9c5db199SXin Li
31*9c5db199SXin Lifrom autotest_lib.client.common_lib import smogcheck_ttci
32*9c5db199SXin Li# Use explicit import to make code more readable
33*9c5db199SXin Lifrom ctypes import c_uint, c_uint32, cdll, c_bool, Structure, POINTER, \
34*9c5db199SXin Li    c_ubyte, c_byte, byref, c_uint16, cast, create_string_buffer, c_uint64, \
35*9c5db199SXin Li    c_char_p, addressof, c_char, pointer
36*9c5db199SXin Li
37*9c5db199SXin Li
38*9c5db199SXin Li# TPM flags
39*9c5db199SXin Li# TODO(tgao): possible to import from trousers/src/include/tss/tss_defines.h?
40*9c5db199SXin LiTSS_KEY_AUTHORIZATION = c_uint32(0x00000001)
41*9c5db199SXin LiTSS_KEY_TSP_SRK = c_uint32(0x04000000)
42*9c5db199SXin LiTSS_POLICY_USAGE = c_uint32(0x00000001)
43*9c5db199SXin LiTSS_OBJECT_TYPE_RSAKEY = c_uint(0x02)
44*9c5db199SXin LiTSS_SECRET_MODE_SHA1 = c_uint32(0x00001000)
45*9c5db199SXin LiTSS_SECRET_MODE_PLAIN = c_uint32(0x00001800)
46*9c5db199SXin LiTSS_TPMCAP_PROP_MANUFACTURER = c_uint(0x12)
47*9c5db199SXin LiTSS_TPMCAP_PROPERTY = c_uint(0x13)
48*9c5db199SXin LiTSS_TPMCAP_VERSION = c_uint(0x14)
49*9c5db199SXin LiTSS_TPMCAP_VERSION_VAL = c_uint32(0x15)
50*9c5db199SXin LiTSS_TPMSTATUS_DISABLEOWNERCLEAR = c_uint32(0x00000001)
51*9c5db199SXin LiTSS_TPMSTATUS_DISABLEFORCECLEAR = c_uint32(0x00000002)
52*9c5db199SXin LiTSS_TPMSTATUS_PHYSICALSETDEACTIVATED = c_uint32(0x00000010)
53*9c5db199SXin LiTSS_TPMSTATUS_SETTEMPDEACTIVATED = c_uint32(0x00000011)
54*9c5db199SXin Li
55*9c5db199SXin Li# TODO(tgao): possible to import from trousers/src/include/tss/tpm.h?
56*9c5db199SXin LiTPM_SHA1_160_HASH_LEN = c_uint(0x14)
57*9c5db199SXin Li
58*9c5db199SXin Li# Path to TSPI shared library.
59*9c5db199SXin LiTSPI_C_LIB = "/usr/lib/libtspi.so.1"
60*9c5db199SXin Li
61*9c5db199SXin Li# Valid operation of tpmSetActive(). Equivalent CLI commands:
62*9c5db199SXin Li# 'status' = tpm_setactive --well-known --status
63*9c5db199SXin Li# 'activate' = tpm_setactive --well-known --active
64*9c5db199SXin Li# 'deactivate' = tpm_setactive --well-known --inactive
65*9c5db199SXin Li# 'temp' = tpm_setactive --well-known --temp
66*9c5db199SXin LiTPM_SETACTIVE_OP = ['status', 'activate', 'deactivate', 'temp']
67*9c5db199SXin Li
68*9c5db199SXin Li# Valid operation of tpmSetClearable(). Equivalent CLI commands:
69*9c5db199SXin Li# 'status' = tpm_setclearable --well-known --status
70*9c5db199SXin Li# 'owner' = tpm_setclearable --well-known --owner
71*9c5db199SXin Li# 'force' = tpm_setclearable --well-known --force
72*9c5db199SXin LiTPM_SETCLEARABLE_OP = ['status', 'owner', 'force']
73*9c5db199SXin Li
74*9c5db199SXin Li# Secret mode for setPolicySecret()
75*9c5db199SXin LiTSS_SECRET_MODE = dict(sha1=TSS_SECRET_MODE_SHA1,
76*9c5db199SXin Li                       plain=TSS_SECRET_MODE_PLAIN)
77*9c5db199SXin Li
78*9c5db199SXin Li
79*9c5db199SXin Liclass SmogcheckError(Exception):
80*9c5db199SXin Li    """Base class for all smogcheck API errors."""
81*9c5db199SXin Li
82*9c5db199SXin Li
83*9c5db199SXin Liclass TpmVersion(Structure):
84*9c5db199SXin Li    """Defines TPM version string struct.
85*9c5db199SXin Li
86*9c5db199SXin Li    Declared in tss/tpm.h and named TPM_VERSION.
87*9c5db199SXin Li    """
88*9c5db199SXin Li    _fields_ = [('major', c_ubyte),
89*9c5db199SXin Li                ('minor', c_ubyte),
90*9c5db199SXin Li                ('revMajor', c_ubyte),
91*9c5db199SXin Li                ('revMinor', c_ubyte)]
92*9c5db199SXin Li
93*9c5db199SXin Li
94*9c5db199SXin Liclass TpmCapVersionInfo(Structure):
95*9c5db199SXin Li    """Defines TPM version info struct.
96*9c5db199SXin Li
97*9c5db199SXin Li    Declared in tss/tpm.h and named TPM_CAP_VERSION_INFO.
98*9c5db199SXin Li    """
99*9c5db199SXin Li    _fields_ = [('tag', c_uint16),
100*9c5db199SXin Li                ('version', TpmVersion),
101*9c5db199SXin Li                ('specLevel', c_uint16),
102*9c5db199SXin Li                ('errataRev', c_ubyte),
103*9c5db199SXin Li                ('tpmVendorID', c_char*4),
104*9c5db199SXin Li                ('vendorSpecific', POINTER(c_ubyte))]
105*9c5db199SXin Li
106*9c5db199SXin Li
107*9c5db199SXin Lidef InitVersionInfo(vi):
108*9c5db199SXin Li    """Utility method to allocate memory for TPM version info.
109*9c5db199SXin Li
110*9c5db199SXin Li    Args:
111*9c5db199SXin Li      vi: a TpmCapVerisonInfo object, just created.
112*9c5db199SXin Li    """
113*9c5db199SXin Li    vi.tpmVendorId = create_string_buffer(4)  # Allocate 4 bytes
114*9c5db199SXin Li    vendorDetail = create_string_buffer(64)   # Allocate 64 bytes
115*9c5db199SXin Li    vi.vendorSpecific = cast(pointer(vendorDetail), POINTER(c_ubyte))
116*9c5db199SXin Li
117*9c5db199SXin Li
118*9c5db199SXin Lidef PrintVersionInfo(vi):
119*9c5db199SXin Li    """Utility method to print TPM version info.
120*9c5db199SXin Li
121*9c5db199SXin Li    Args:
122*9c5db199SXin Li      vi: a TpmCapVerisonInfo object.
123*9c5db199SXin Li    """
124*9c5db199SXin Li    logging.info('  TPM 1.2 Version Info:\n')
125*9c5db199SXin Li    logging.info('  Chip Version:  %d.%d.%d.%d.', vi.version.major,
126*9c5db199SXin Li                 vi.version.minor, vi.version.revMajor, vi.version.revMinor)
127*9c5db199SXin Li    logging.info('  Spec Level:  %d', vi.specLevel)
128*9c5db199SXin Li    logging.info('  Errata Revision:  %d', vi.errataRev)
129*9c5db199SXin Li    vendorId = [i for i in vi.tpmVendorID if i]
130*9c5db199SXin Li    logging.info('  TPM Vendor ID:  %s', ''.join(vendorId))
131*9c5db199SXin Li    # TODO(tgao): handle the case when there's no vendor specific data.
132*9c5db199SXin Li    logging.info('  Vendor Specific data (first 4 bytes in Hex):  '
133*9c5db199SXin Li                 '%.2x %.2x %.2x %.2x', vi.vendorSpecific[0],
134*9c5db199SXin Li                 vi.vendorSpecific[1], vi.vendorSpecific[2],
135*9c5db199SXin Li                 vi.vendorSpecific[3])
136*9c5db199SXin Li
137*9c5db199SXin Li
138*9c5db199SXin Lidef PrintSelfTestResult(str_len, pResult):
139*9c5db199SXin Li    """Utility method to print TPM self test result.
140*9c5db199SXin Li
141*9c5db199SXin Li    Args:
142*9c5db199SXin Li      str_len: an integer, length of string pointed to by pResult.
143*9c5db199SXin Li      pResult: a c_char_p, pointer to result.
144*9c5db199SXin Li    """
145*9c5db199SXin Li    out = []
146*9c5db199SXin Li    for i in range(str_len):
147*9c5db199SXin Li        if i and not i % 32:
148*9c5db199SXin Li            out.append('\t')
149*9c5db199SXin Li        if not i % 4:
150*9c5db199SXin Li            out.append(' ')
151*9c5db199SXin Li        b = pResult.value[i]
152*9c5db199SXin Li        out.append('%02x' % ord(b))
153*9c5db199SXin Li    logging.info('  TPM Test Results: %s', ''.join(out))
154*9c5db199SXin Li
155*9c5db199SXin Li
156*9c5db199SXin Liclass TpmController(object):
157*9c5db199SXin Li    """Object to interact with TPM module for testing."""
158*9c5db199SXin Li
159*9c5db199SXin Li    def __init__(self):
160*9c5db199SXin Li        """Constructor.
161*9c5db199SXin Li
162*9c5db199SXin Li        Mandatory params:
163*9c5db199SXin Li          hContext: a c_uint32, context object handle.
164*9c5db199SXin Li          _contextSet: a boolean, True if TPM context is set.
165*9c5db199SXin Li          hTpm: a c_uint32, TPM object handle.
166*9c5db199SXin Li          hTpmPolicy: a c_uint32, TPM policy object handle.
167*9c5db199SXin Li          tspi_lib: a shared library object (libtspi.so).
168*9c5db199SXin Li
169*9c5db199SXin Li        Raises:
170*9c5db199SXin Li          SmogcheckError: if error initializing TpmController.
171*9c5db199SXin Li        """
172*9c5db199SXin Li        self.hContext = c_uint32(0)
173*9c5db199SXin Li        self._contextSet = False
174*9c5db199SXin Li        self.hTpm = c_uint32(0)
175*9c5db199SXin Li        self.hTpmPolicy = c_uint32(0)
176*9c5db199SXin Li
177*9c5db199SXin Li        logging.info('Attempt to load shared library %s', TSPI_C_LIB)
178*9c5db199SXin Li        try:
179*9c5db199SXin Li            self.tspi_lib = cdll.LoadLibrary(TSPI_C_LIB)
180*9c5db199SXin Li        except OSError as e:
181*9c5db199SXin Li            raise SmogcheckError('Error loading C library %s: %r' %
182*9c5db199SXin Li                                 (TSPI_C_LIB, e))
183*9c5db199SXin Li        logging.info('Successfully loaded shared library %s', TSPI_C_LIB)
184*9c5db199SXin Li
185*9c5db199SXin Li    def closeContext(self):
186*9c5db199SXin Li        """Closes TPM context and cleans up.
187*9c5db199SXin Li
188*9c5db199SXin Li        Returns:
189*9c5db199SXin Li          an integer, 0 for success and -1 for error.
190*9c5db199SXin Li        """
191*9c5db199SXin Li        if not self._contextSet:
192*9c5db199SXin Li            logging.debug('TPM context NOT set.')
193*9c5db199SXin Li            return 0
194*9c5db199SXin Li
195*9c5db199SXin Li        ret = -1
196*9c5db199SXin Li        # Calling the pointer type without an argument creates a NULL pointer
197*9c5db199SXin Li        if self.tspi_lib.Tspi_Context_FreeMemory(self.hContext,
198*9c5db199SXin Li                                                 POINTER(c_byte)()) != 0:
199*9c5db199SXin Li            logging.error('Error freeing memory when closing TPM context')
200*9c5db199SXin Li        else:
201*9c5db199SXin Li            logging.debug('Tspi_Context_FreeMemory() success')
202*9c5db199SXin Li
203*9c5db199SXin Li        if self.tspi_lib.Tspi_Context_Close(self.hContext) != 0:
204*9c5db199SXin Li            logging.error('Error closing TPM context')
205*9c5db199SXin Li        else:
206*9c5db199SXin Li            logging.debug('Tspi_Context_Close() success')
207*9c5db199SXin Li            ret = 0
208*9c5db199SXin Li            self._contextSet = False
209*9c5db199SXin Li
210*9c5db199SXin Li        return ret
211*9c5db199SXin Li
212*9c5db199SXin Li    def _closeContextObject(self, hObject):
213*9c5db199SXin Li        """Closes TPM context object.
214*9c5db199SXin Li
215*9c5db199SXin Li        Args:
216*9c5db199SXin Li          hObject: an integer, basic object handle.
217*9c5db199SXin Li
218*9c5db199SXin Li        Raises:
219*9c5db199SXin Li          SmogcheckError: if an error is encountered.
220*9c5db199SXin Li        """
221*9c5db199SXin Li        if self.tspi_lib.Tspi_Context_CloseObject(self.hContext, hObject) != 0:
222*9c5db199SXin Li            raise SmogcheckError('Error closing TPM context object')
223*9c5db199SXin Li
224*9c5db199SXin Li        logging.debug('Tspi_Context_CloseObject() success')
225*9c5db199SXin Li
226*9c5db199SXin Li    def setupContext(self):
227*9c5db199SXin Li        """Sets up tspi context for TPM access.
228*9c5db199SXin Li
229*9c5db199SXin Li        TPM context cannot be reused. Therefore, each new Tspi_* command would
230*9c5db199SXin Li        require a new context to be set up before execution and closing that
231*9c5db199SXin Li        context after execution (or error).
232*9c5db199SXin Li
233*9c5db199SXin Li        Raises:
234*9c5db199SXin Li          SmogcheckError: if an error is encountered.
235*9c5db199SXin Li        """
236*9c5db199SXin Li        if self._contextSet:
237*9c5db199SXin Li            logging.debug('TPM context already set.')
238*9c5db199SXin Li            return
239*9c5db199SXin Li
240*9c5db199SXin Li        if self.tspi_lib.Tspi_Context_Create(byref(self.hContext)) != 0:
241*9c5db199SXin Li            raise SmogcheckError('Error creating tspi context')
242*9c5db199SXin Li
243*9c5db199SXin Li        logging.info('Created tspi context = 0x%x', self.hContext.value)
244*9c5db199SXin Li
245*9c5db199SXin Li        if self.tspi_lib.Tspi_Context_Connect(self.hContext,
246*9c5db199SXin Li                                              POINTER(c_uint16)()) != 0:
247*9c5db199SXin Li            raise SmogcheckError('Error connecting to tspi context')
248*9c5db199SXin Li
249*9c5db199SXin Li        logging.info('Connected to tspi context')
250*9c5db199SXin Li
251*9c5db199SXin Li        if self.tspi_lib.Tspi_Context_GetTpmObject(self.hContext,
252*9c5db199SXin Li                                                   byref(self.hTpm)) != 0:
253*9c5db199SXin Li            raise SmogcheckError('Error getting TPM object from tspi context')
254*9c5db199SXin Li
255*9c5db199SXin Li        logging.info('Got tpm object from tspi context = 0x%x', self.hTpm.value)
256*9c5db199SXin Li        self._contextSet = True
257*9c5db199SXin Li
258*9c5db199SXin Li    def _getTpmStatus(self, flag, bValue):
259*9c5db199SXin Li        """Wrapper function to call Tspi_TPM_GetStatus().
260*9c5db199SXin Li
261*9c5db199SXin Li        Args:
262*9c5db199SXin Li          flag: a c_uint, TPM status info flag, values defined in C header file
263*9c5db199SXin Li                "tss/tss_defines.h".
264*9c5db199SXin Li          bValue: a c_bool, place holder for specific TPM flag bit value (0/1).
265*9c5db199SXin Li
266*9c5db199SXin Li        Raises:
267*9c5db199SXin Li          SmogcheckError: if an error is encountered.
268*9c5db199SXin Li        """
269*9c5db199SXin Li        result = self.tspi_lib.Tspi_TPM_GetStatus(self.hTpm, flag,
270*9c5db199SXin Li                                                  byref(bValue))
271*9c5db199SXin Li        if result != 0:
272*9c5db199SXin Li            msg = ('Error (0x%x) getting status for flag 0x%x' %
273*9c5db199SXin Li                   (result, flag.value))
274*9c5db199SXin Li            raise SmogcheckError(msg)
275*9c5db199SXin Li
276*9c5db199SXin Li        logging.info('Tspi_TPM_GetStatus(): success for flag 0x%x',
277*9c5db199SXin Li                     flag.value)
278*9c5db199SXin Li
279*9c5db199SXin Li    def _setTpmStatus(self, flag, bValue):
280*9c5db199SXin Li        """Wrapper function to call Tspi_TPM_GetStatus().
281*9c5db199SXin Li
282*9c5db199SXin Li        Args:
283*9c5db199SXin Li          flag: a c_uint, TPM status info flag.
284*9c5db199SXin Li          bValue: a c_bool, place holder for specific TPM flag bit value (0/1).
285*9c5db199SXin Li
286*9c5db199SXin Li        Raises:
287*9c5db199SXin Li          SmogcheckError: if an error is encountered.
288*9c5db199SXin Li        """
289*9c5db199SXin Li        result = self.tspi_lib.Tspi_TPM_SetStatus(self.hTpm, flag, bValue)
290*9c5db199SXin Li        if result != 0:
291*9c5db199SXin Li            msg = ('Error (0x%x) setting status for flag 0x%x' %
292*9c5db199SXin Li                   (result, flag.value))
293*9c5db199SXin Li            raise SmogcheckError(msg)
294*9c5db199SXin Li
295*9c5db199SXin Li        logging.info('Tspi_TPM_SetStatus(): success for flag 0x%x',
296*9c5db199SXin Li                     flag.value)
297*9c5db199SXin Li
298*9c5db199SXin Li    def getPolicyObject(self, hTpm=None, hPolicy=None):
299*9c5db199SXin Li        """Get TPM policy object.
300*9c5db199SXin Li
301*9c5db199SXin Li        Args:
302*9c5db199SXin Li          hTpm: a c_uint, TPM object handle.
303*9c5db199SXin Li          hPolicy: a c_uint, TPM policy object handle.
304*9c5db199SXin Li
305*9c5db199SXin Li        Raises:
306*9c5db199SXin Li          SmogcheckError: if an error is encountered.
307*9c5db199SXin Li        """
308*9c5db199SXin Li        if hTpm is None:
309*9c5db199SXin Li            hTpm = self.hTpm
310*9c5db199SXin Li
311*9c5db199SXin Li        if hPolicy is None:
312*9c5db199SXin Li            hPolicy = self.hTpmPolicy
313*9c5db199SXin Li
314*9c5db199SXin Li        logging.debug('Tspi_GetPolicyObject(): hTpm = 0x%x, hPolicy = 0x%x',
315*9c5db199SXin Li                      hTpm.value, hPolicy.value)
316*9c5db199SXin Li        result = self.tspi_lib.Tspi_GetPolicyObject(hTpm, TSS_POLICY_USAGE,
317*9c5db199SXin Li                                                    byref(hPolicy))
318*9c5db199SXin Li        if result != 0:
319*9c5db199SXin Li            msg = 'Error (0x%x) getting TPM policy object' % result
320*9c5db199SXin Li            raise SmogcheckError(msg)
321*9c5db199SXin Li
322*9c5db199SXin Li        logging.debug('Tspi_GetPolicyObject() success hTpm = 0x%x, '
323*9c5db199SXin Li                      'hPolicy = 0x%x', hTpm.value, hPolicy.value)
324*9c5db199SXin Li
325*9c5db199SXin Li    def setPolicySecret(self, hPolicy=None, pSecret=None, secret_mode=None):
326*9c5db199SXin Li        """Sets TPM policy secret.
327*9c5db199SXin Li
328*9c5db199SXin Li        Args:
329*9c5db199SXin Li          hPolicy: a c_uint, TPM policy object handle.
330*9c5db199SXin Li          pSecret: a pointer to a byte array, which holds the TSS secret.
331*9c5db199SXin Li          secret_mode: a string, valid values are keys of TSS_SECRET_MODE.
332*9c5db199SXin Li
333*9c5db199SXin Li        Raises:
334*9c5db199SXin Li          SmogcheckError: if an error is encountered.
335*9c5db199SXin Li        """
336*9c5db199SXin Li        if hPolicy is None:
337*9c5db199SXin Li            hPolicy = self.hTpmPolicy
338*9c5db199SXin Li
339*9c5db199SXin Li        if pSecret is None:
340*9c5db199SXin Li            raise SmogcheckError('setPolicySecret(): pSecret cannot be None')
341*9c5db199SXin Li
342*9c5db199SXin Li        if secret_mode is None or secret_mode not in TSS_SECRET_MODE:
343*9c5db199SXin Li            raise SmogcheckError('setPolicySecret(): invalid secret_mode')
344*9c5db199SXin Li
345*9c5db199SXin Li        logging.debug('Tspi_Policy_SetSecret(): hPolicy = 0x%x, secret_mode '
346*9c5db199SXin Li                      '(%r) = %r', hPolicy.value, secret_mode,
347*9c5db199SXin Li                      TSS_SECRET_MODE[secret_mode])
348*9c5db199SXin Li
349*9c5db199SXin Li        result = self.tspi_lib.Tspi_Policy_SetSecret(
350*9c5db199SXin Li            hPolicy, TSS_SECRET_MODE[secret_mode], TPM_SHA1_160_HASH_LEN,
351*9c5db199SXin Li            pSecret)
352*9c5db199SXin Li        if result != 0:
353*9c5db199SXin Li            msg = 'Error (0x%x) setting TPM policy secret' % result
354*9c5db199SXin Li            raise SmogcheckError(msg)
355*9c5db199SXin Li
356*9c5db199SXin Li        logging.debug('Tspi_Policy_SetSecret() success, hPolicy = 0x%x',
357*9c5db199SXin Li                      hPolicy.value)
358*9c5db199SXin Li
359*9c5db199SXin Li    def getTpmVersion(self):
360*9c5db199SXin Li        """Gets TPM version info.
361*9c5db199SXin Li
362*9c5db199SXin Li        Implementation based on tpm-tools-1.3.4/src/tpm_mgmt/tpm_version.c
363*9c5db199SXin Li        Downloaded from:
364*9c5db199SXin Li          http://sourceforge.net/projects/trousers/files/tpm-tools/1.3.4/\
365*9c5db199SXin Li          tpm-tools-1.3.4.tar.gz
366*9c5db199SXin Li
367*9c5db199SXin Li        Raises:
368*9c5db199SXin Li          SmogcheckError: if an error is encountered.
369*9c5db199SXin Li        """
370*9c5db199SXin Li        uiResultLen = c_uint32(0)
371*9c5db199SXin Li        pResult = c_char_p()
372*9c5db199SXin Li        offset = c_uint64(0)
373*9c5db199SXin Li        versionInfo = TpmCapVersionInfo()
374*9c5db199SXin Li        InitVersionInfo(versionInfo)
375*9c5db199SXin Li
376*9c5db199SXin Li        logging.debug('Successfully set up tspi context: hTpm = %r', self.hTpm)
377*9c5db199SXin Li
378*9c5db199SXin Li        result = self.tspi_lib.Tspi_TPM_GetCapability(
379*9c5db199SXin Li            self.hTpm, TSS_TPMCAP_VERSION_VAL, 0, POINTER(c_byte)(),
380*9c5db199SXin Li            byref(uiResultLen), byref(pResult))
381*9c5db199SXin Li        if result != 0:
382*9c5db199SXin Li            msg = 'Error (0x%x) getting TPM capability, pResult = %r' % (
383*9c5db199SXin Li                result, pResult.value)
384*9c5db199SXin Li            raise SmogcheckError(msg)
385*9c5db199SXin Li
386*9c5db199SXin Li        logging.info('Successfully received TPM capability: '
387*9c5db199SXin Li                     'uiResultLen = %d, pResult=%r', uiResultLen.value,
388*9c5db199SXin Li                     pResult.value)
389*9c5db199SXin Li        result = self.tspi_lib.Trspi_UnloadBlob_CAP_VERSION_INFO(
390*9c5db199SXin Li            byref(offset), pResult, cast(byref(versionInfo),
391*9c5db199SXin Li                                         POINTER(c_byte)))
392*9c5db199SXin Li        if result != 0:
393*9c5db199SXin Li            msg = 'Error (0x%x) unloading TPM CAP version info' % result
394*9c5db199SXin Li            raise SmogcheckError(msg)
395*9c5db199SXin Li
396*9c5db199SXin Li        PrintVersionInfo(versionInfo)
397*9c5db199SXin Li
398*9c5db199SXin Li    def runTpmSelfTest(self):
399*9c5db199SXin Li        """Executes TPM self test.
400*9c5db199SXin Li
401*9c5db199SXin Li        Implementation based on tpm-tools-1.3.4/src/tpm_mgmt/tpm_selftest.c
402*9c5db199SXin Li
403*9c5db199SXin Li        Raises:
404*9c5db199SXin Li          SmogcheckError: if an error is encountered.
405*9c5db199SXin Li        """
406*9c5db199SXin Li        uiResultLen = c_uint32(0)
407*9c5db199SXin Li        pResult = c_char_p()
408*9c5db199SXin Li        self.setupContext()
409*9c5db199SXin Li
410*9c5db199SXin Li        logging.debug('Successfully set up tspi context: hTpm = 0x%x',
411*9c5db199SXin Li                      self.hTpm.value)
412*9c5db199SXin Li
413*9c5db199SXin Li        result = self.tspi_lib.Tspi_TPM_SelfTestFull(self.hTpm)
414*9c5db199SXin Li        if result != 0:
415*9c5db199SXin Li            self.closeContext()
416*9c5db199SXin Li            raise SmogcheckError('Error (0x%x) with TPM self test' % result)
417*9c5db199SXin Li
418*9c5db199SXin Li        logging.info('Successfully executed TPM self test: hTpm = 0x%x',
419*9c5db199SXin Li                     self.hTpm.value)
420*9c5db199SXin Li        result = self.tspi_lib.Tspi_TPM_GetTestResult(
421*9c5db199SXin Li            self.hTpm, byref(uiResultLen), byref(pResult))
422*9c5db199SXin Li        if result != 0:
423*9c5db199SXin Li            self.closeContext()
424*9c5db199SXin Li            raise SmogcheckError('Error (0x%x) getting test results' % result)
425*9c5db199SXin Li
426*9c5db199SXin Li        logging.info('TPM self test results: uiResultLen = %d, pResult=%r',
427*9c5db199SXin Li                     uiResultLen.value, pResult.value)
428*9c5db199SXin Li        PrintSelfTestResult(uiResultLen.value, pResult)
429*9c5db199SXin Li        self.closeContext()
430*9c5db199SXin Li
431*9c5db199SXin Li    def takeTpmOwnership(self):
432*9c5db199SXin Li        """Take TPM ownership.
433*9c5db199SXin Li
434*9c5db199SXin Li        Implementation based on tpm-tools-1.3.4/src/tpm_mgmt/tpm_takeownership.c
435*9c5db199SXin Li
436*9c5db199SXin Li        Raises:
437*9c5db199SXin Li          SmogcheckError: if an error is encountered.
438*9c5db199SXin Li        """
439*9c5db199SXin Li        hSrk = c_uint32(0)  # TPM Storage Root Key
440*9c5db199SXin Li        hSrkPolicy = c_uint32(0)
441*9c5db199SXin Li        # Defaults each byte value to 0x00
442*9c5db199SXin Li        well_known_secret = create_string_buffer(20)
443*9c5db199SXin Li        pSecret = c_char_p(addressof(well_known_secret))
444*9c5db199SXin Li
445*9c5db199SXin Li        self.setupContext()
446*9c5db199SXin Li        logging.debug('Successfully set up tspi context: hTpm = 0x%x',
447*9c5db199SXin Li                      self.hTpm.value)
448*9c5db199SXin Li
449*9c5db199SXin Li        try:
450*9c5db199SXin Li            self.getPolicyObject()
451*9c5db199SXin Li            self.setPolicySecret(pSecret=pSecret, secret_mode='sha1')
452*9c5db199SXin Li        except SmogcheckError:
453*9c5db199SXin Li            if hSrk != 0:
454*9c5db199SXin Li                self._closeContextObject(hSrk)
455*9c5db199SXin Li            self.closeContext()
456*9c5db199SXin Li            raise  # re-raise
457*9c5db199SXin Li
458*9c5db199SXin Li        flag = TSS_KEY_TSP_SRK.value | TSS_KEY_AUTHORIZATION.value
459*9c5db199SXin Li        result = self.tspi_lib.Tspi_Context_CreateObject(
460*9c5db199SXin Li            self.hContext, TSS_OBJECT_TYPE_RSAKEY, flag, byref(hSrk))
461*9c5db199SXin Li        if result != 0:
462*9c5db199SXin Li            raise SmogcheckError('Error (0x%x) creating context object' %
463*9c5db199SXin Li                                 result)
464*9c5db199SXin Li        logging.debug('hTpm = 0x%x, flag = 0x%x, hSrk = 0x%x',
465*9c5db199SXin Li                      self.hTpm.value, flag, hSrk.value)  # DEBUG
466*9c5db199SXin Li
467*9c5db199SXin Li        try:
468*9c5db199SXin Li            self.getPolicyObject(hTpm=hSrk, hPolicy=hSrkPolicy)
469*9c5db199SXin Li            self.setPolicySecret(hPolicy=hSrkPolicy, pSecret=pSecret,
470*9c5db199SXin Li                                 secret_mode='sha1')
471*9c5db199SXin Li        except SmogcheckError:
472*9c5db199SXin Li            if hSrk != 0:
473*9c5db199SXin Li                self._closeContextObject(hSrk)
474*9c5db199SXin Li            self.closeContext()
475*9c5db199SXin Li            raise  # re-raise
476*9c5db199SXin Li
477*9c5db199SXin Li        logging.debug('Successfully set up SRK policy: secret = %r, '
478*9c5db199SXin Li                      'hSrk = 0x%x, hSrkPolicy = 0x%x',
479*9c5db199SXin Li                      well_known_secret.value, hSrk.value, hSrkPolicy.value)
480*9c5db199SXin Li
481*9c5db199SXin Li        start_time = datetime.datetime.now()
482*9c5db199SXin Li        result = self.tspi_lib.Tspi_TPM_TakeOwnership(self.hTpm, hSrk,
483*9c5db199SXin Li                                                      c_uint(0))
484*9c5db199SXin Li        end_time = datetime.datetime.now()
485*9c5db199SXin Li        if result != 0:
486*9c5db199SXin Li            logging.info('Tspi_TPM_TakeOwnership error')
487*9c5db199SXin Li            self._closeContextObject(hSrk)
488*9c5db199SXin Li            self.closeContext()
489*9c5db199SXin Li            raise SmogcheckError('Error (0x%x) taking TPM ownership' % result)
490*9c5db199SXin Li
491*9c5db199SXin Li        logging.info('Successfully took TPM ownership')
492*9c5db199SXin Li        self._closeContextObject(hSrk)
493*9c5db199SXin Li        self.closeContext()
494*9c5db199SXin Li        return smogcheck_ttci.computeTimeElapsed(end_time, start_time)
495*9c5db199SXin Li
496*9c5db199SXin Li    def clearTpm(self):
497*9c5db199SXin Li        """Return TPM to default state.
498*9c5db199SXin Li
499*9c5db199SXin Li        Implementation based on tpm-tools-1.3.4/src/tpm_mgmt/tpm_clear.c
500*9c5db199SXin Li
501*9c5db199SXin Li        Raises:
502*9c5db199SXin Li          SmogcheckError: if an error is encountered.
503*9c5db199SXin Li        """
504*9c5db199SXin Li        logging.debug('Successfully set up tspi context: hTpm = %r', self.hTpm)
505*9c5db199SXin Li
506*9c5db199SXin Li        result = self.tspi_lib.Tspi_TPM_ClearOwner(self.hTpm, True)
507*9c5db199SXin Li        if result != 0:
508*9c5db199SXin Li            raise SmogcheckError('Error (0x%x) clearing TPM' % result)
509*9c5db199SXin Li
510*9c5db199SXin Li        logging.info('Successfully cleared TPM')
511*9c5db199SXin Li
512*9c5db199SXin Li    def setTpmActive(self, op):
513*9c5db199SXin Li        """Change TPM active state.
514*9c5db199SXin Li
515*9c5db199SXin Li        Implementation based on tpm-tools-1.3.4/src/tpm_mgmt/tpm_activate.c
516*9c5db199SXin Li
517*9c5db199SXin Li        Args:
518*9c5db199SXin Li          op: a string, desired operation. Valid values are defined in
519*9c5db199SXin Li              TPM_SETACTIVE_OP.
520*9c5db199SXin Li
521*9c5db199SXin Li        Raises:
522*9c5db199SXin Li          SmogcheckError: if an error is encountered.
523*9c5db199SXin Li        """
524*9c5db199SXin Li        bValue = c_bool()
525*9c5db199SXin Li        # Defaults each byte value to 0x00
526*9c5db199SXin Li        well_known_secret = create_string_buffer(20)
527*9c5db199SXin Li        pSecret = c_char_p(addressof(well_known_secret))
528*9c5db199SXin Li
529*9c5db199SXin Li        if op not in TPM_SETACTIVE_OP:
530*9c5db199SXin Li            msg = ('Invalid op (%s) for tpmSetActive(). Valid values are %r' %
531*9c5db199SXin Li                   (op, TPM_SETACTIVE_OP))
532*9c5db199SXin Li            raise SmogcheckError(msg)
533*9c5db199SXin Li
534*9c5db199SXin Li        logging.debug('Successfully set up tspi context: hTpm = %r', self.hTpm)
535*9c5db199SXin Li
536*9c5db199SXin Li        if op == 'status':
537*9c5db199SXin Li            self.getPolicyObject()
538*9c5db199SXin Li            self.setPolicySecret(pSecret=pSecret, secret_mode='sha1')
539*9c5db199SXin Li
540*9c5db199SXin Li            self._getTpmStatus(
541*9c5db199SXin Li                TSS_TPMSTATUS_PHYSICALSETDEACTIVATED, bValue)
542*9c5db199SXin Li            logging.info('Persistent Deactivated Status: %s', bValue.value)
543*9c5db199SXin Li
544*9c5db199SXin Li            self._getTpmStatus(
545*9c5db199SXin Li                TSS_TPMSTATUS_SETTEMPDEACTIVATED, bValue)
546*9c5db199SXin Li            logging.info('Volatile Deactivated Status: %s', bValue.value)
547*9c5db199SXin Li        elif op == 'activate':
548*9c5db199SXin Li            self._setTpmStatus(
549*9c5db199SXin Li                TSS_TPMSTATUS_PHYSICALSETDEACTIVATED, False)
550*9c5db199SXin Li            logging.info('Successfully activated TPM')
551*9c5db199SXin Li        elif op == 'deactivate':
552*9c5db199SXin Li            self._setTpmStatus(
553*9c5db199SXin Li                TSS_TPMSTATUS_PHYSICALSETDEACTIVATED, True)
554*9c5db199SXin Li            logging.info('Successfully deactivated TPM')
555*9c5db199SXin Li        elif op == 'temp':
556*9c5db199SXin Li            self._setTpmStatus(
557*9c5db199SXin Li                TSS_TPMSTATUS_SETTEMPDEACTIVATED, True)
558*9c5db199SXin Li            logging.info('Successfully deactivated TPM for current boot')
559*9c5db199SXin Li
560*9c5db199SXin Li    def setTpmClearable(self, op):
561*9c5db199SXin Li        """Disable TPM clear operations.
562*9c5db199SXin Li
563*9c5db199SXin Li        Implementation based on tpm-tools-1.3.4/src/tpm_mgmt/tpm_clearable.c
564*9c5db199SXin Li
565*9c5db199SXin Li        Args:
566*9c5db199SXin Li          op: a string, desired operation. Valid values are defined in
567*9c5db199SXin Li              TPM_SETCLEARABLE_OP.
568*9c5db199SXin Li
569*9c5db199SXin Li        Raises:
570*9c5db199SXin Li          SmogcheckError: if an error is encountered.
571*9c5db199SXin Li        """
572*9c5db199SXin Li        bValue = c_bool()
573*9c5db199SXin Li        # Defaults each byte value to 0x00
574*9c5db199SXin Li        well_known_secret = create_string_buffer(20)
575*9c5db199SXin Li        pSecret = c_char_p(addressof(well_known_secret))
576*9c5db199SXin Li
577*9c5db199SXin Li        if op not in TPM_SETCLEARABLE_OP:
578*9c5db199SXin Li            msg = ('Invalid op (%s) for tpmSetClearable(). Valid values are %r'
579*9c5db199SXin Li                   % (op, TPM_SETCLEARABLE_OP))
580*9c5db199SXin Li            raise SmogcheckError(msg)
581*9c5db199SXin Li
582*9c5db199SXin Li        logging.debug('Successfully set up tspi context: hTpm = %r', self.hTpm)
583*9c5db199SXin Li
584*9c5db199SXin Li        if op == 'status':
585*9c5db199SXin Li            self.getPolicyObject()
586*9c5db199SXin Li            self.setPolicySecret(pSecret=pSecret, secret_mode='sha1')
587*9c5db199SXin Li
588*9c5db199SXin Li            self._getTpmStatus(
589*9c5db199SXin Li                TSS_TPMSTATUS_DISABLEOWNERCLEAR, bValue)
590*9c5db199SXin Li            logging.info('Owner Clear Disabled: %s', bValue.value)
591*9c5db199SXin Li
592*9c5db199SXin Li            self._getTpmStatus(
593*9c5db199SXin Li                TSS_TPMSTATUS_DISABLEFORCECLEAR, bValue)
594*9c5db199SXin Li            logging.info('Force Clear Disabled: %s', bValue.value)
595*9c5db199SXin Li        elif op == 'owner':
596*9c5db199SXin Li            self.getPolicyObject()
597*9c5db199SXin Li            self.setPolicySecret(pSecret=pSecret, secret_mode='sha1')
598*9c5db199SXin Li
599*9c5db199SXin Li            self._setTpmStatus(
600*9c5db199SXin Li                TSS_TPMSTATUS_DISABLEOWNERCLEAR, False)
601*9c5db199SXin Li            logging.info('Successfully disabled Owner Clear')
602*9c5db199SXin Li        elif op == 'force':
603*9c5db199SXin Li            self._setTpmStatus(
604*9c5db199SXin Li                TSS_TPMSTATUS_DISABLEFORCECLEAR, True)
605*9c5db199SXin Li            logging.info('Successfully disabled Force Clear')
606