• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5import hashlib, logging
6
7from autotest_lib.client.common_lib import error
8from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
9
10
11class firmware_TPMExtend(FirmwareTest):
12    """Test to ensure TPM PCRs are extended correctly."""
13    version = 1
14
15    def initialize(self, host, cmdline_args):
16        super(firmware_TPMExtend, self).initialize(host, cmdline_args)
17        self.switcher.setup_mode('normal')
18        self.setup_usbkey(usbkey=True, host=False)
19
20    def _tpm1_check_pcr(self, num, hash_obj):
21        pcrs_file = '/sys/class/*/tpm0/device/pcrs'
22        pcrs = '\n'.join(self.faft_client.system.run_shell_command_get_output(
23                        'cat %s' % pcrs_file))
24        logging.debug('Dumping PCRs read from device: \n%s', pcrs)
25        extended = hashlib.sha1(b'\0' * 20 + hash_obj.digest()[:20]).hexdigest()
26        spaced = ' '.join(extended[i:i+2] for i in xrange(0, len(extended), 2))
27        logging.debug('PCR %d should contain hash: %s', num, spaced)
28        return ('PCR-%.2d: %s' % (num, spaced.upper())) in pcrs
29
30    def _tpm2_check_pcr(self, num, hash_obj):
31        out = self.faft_client.system.run_shell_command_get_output(
32                'trunks_client --read_pcr --index=%d' % num)[0]
33        logging.debug('PCR %d read from device: %s', num, out)
34        padded = (hash_obj.digest() + b'\0' * 12)[:32]
35        extended = hashlib.sha256(b'\0' * 32 + padded).hexdigest().upper()
36        logging.debug('PCR %d should contain hash: %s', num, extended)
37        return extended in out
38
39    def _check_pcr(self, num, hash_obj):
40        """Returns true iff PCR |num| was extended with hashlib |hash_obj|."""
41        if '1.' in self.faft_client.tpm.get_tpm_version():
42            return self._tpm1_check_pcr(num, hash_obj)
43        else:
44            return self._tpm2_check_pcr(num, hash_obj)
45
46    def run_once(self):
47        """Runs a single iteration of the test."""
48        logging.info('Verifying HWID digest in PCR1')
49        hwid = self.faft_client.system.run_shell_command_get_output(
50                'crossystem hwid')[0]
51        logging.debug('HWID reported by device is: %s', hwid)
52        if not self._check_pcr(1, hashlib.sha256(hwid)):
53            raise error.TestFail('PCR1 was not extended with SHA256 of HWID!')
54
55        logging.info('Verifying bootmode digest in PCR0 in normal mode')
56        self.check_state((self.checkers.crossystem_checker, {
57                            'devsw_boot': '0',
58                            'mainfw_type': 'normal'
59                            }))
60        # dev_mode: 0, rec_mode: 0, keyblock_flags: "normal" (1)
61        if not self._check_pcr(0, hashlib.sha1(chr(0) + chr(0) + chr(1))):
62            raise error.TestFail('PCR0 was not extended with bootmode 0|0|1!')
63
64        logging.info('Verifying bootmode digest in PCR0 in recovery mode')
65        self.switcher.reboot_to_mode(to_mode='rec')
66        self.check_state((self.checkers.crossystem_checker, {
67                            'devsw_boot': '0',
68                            'mainfw_type': 'recovery'
69                            }))
70        # dev_mode: 0, rec_mode: 1, keyblock_flags: "unknown" (0)
71        if not self._check_pcr(0, hashlib.sha1(chr(0) + chr(1) + chr(0))):
72            raise error.TestFail('PCR0 was not extended with bootmode 0|1|0!')
73
74        logging.info('Transitioning to dev mode for next test')
75        self.switcher.reboot_to_mode(to_mode='dev')
76
77        logging.info('Verifying bootmode digest in PCR0 in developer mode')
78        self.check_state((self.checkers.crossystem_checker, {
79                            'devsw_boot': '1',
80                            'mainfw_type': 'developer'
81                            }))
82        # dev_mode: 1, rec_mode: 0, keyblock_flags: "normal" (1)
83        if not self._check_pcr(0, hashlib.sha1(chr(1) + chr(0) + chr(1))):
84            raise error.TestFail('PCR0 was not extended with bootmode 1|0|1!')
85
86        logging.info('Verifying bootmode digest in PCR0 in dev-recovery mode')
87        self.switcher.reboot_to_mode(to_mode='rec')
88        self.check_state((self.checkers.crossystem_checker, {
89                            'devsw_boot': '1',
90                            'mainfw_type': 'recovery'
91                            }))
92        # dev_mode: 1, rec_mode: 1, keyblock_flags: "unknown" (0)
93        if not self._check_pcr(0, hashlib.sha1(chr(1) + chr(1) + chr(0))):
94            raise error.TestFail('PCR0 was not extended with bootmode 1|1|0!')
95
96        logging.info('All done, returning to normal mode')
97        self.switcher.reboot_to_mode(to_mode='normal')
98