| # Copyright 2014 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import hashlib, logging |
| |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.server.cros.faft.firmware_test import FirmwareTest |
| |
| |
| class firmware_TPMExtend(FirmwareTest): |
| """Test to ensure TPM PCRs are extended correctly.""" |
| version = 1 |
| |
| def initialize(self, host, cmdline_args): |
| super(firmware_TPMExtend, self).initialize(host, cmdline_args) |
| self.switcher.setup_mode('normal') |
| self.setup_usbkey(usbkey=True, host=False) |
| |
| def _check_pcr(self, num, hash_obj): |
| """Returns true iff PCR |num| was extended with hashlib |hash_obj|.""" |
| pcrs_file='/sys/class/*/tpm0/device/pcrs' |
| pcrs = '\n'.join(self.faft_client.system.run_shell_command_get_output( |
| 'cat %s' % pcrs_file)) |
| logging.debug('Dumping PCRs read from device: \n%s', pcrs) |
| extended = hashlib.sha1('\0' * 20 + hash_obj.digest()[:20]).hexdigest() |
| spaced = ' '.join(extended[i:i+2] for i in xrange(0, len(extended), 2)) |
| logging.debug('PCR %d should contain hash: %s', num, spaced) |
| return ('PCR-%.2d: %s' % (num, spaced.upper())) in pcrs |
| |
| def run_once(self): |
| logging.info('Verifying HWID digest in PCR1') |
| hwid = self.faft_client.system.run_shell_command_get_output( |
| 'crossystem hwid')[0] |
| logging.debug('HWID reported by device is: %s', hwid) |
| if not self._check_pcr(1, hashlib.sha256(hwid)): |
| error.TestFail('PCR1 was not extended with SHA256 digest of HWID!') |
| |
| logging.info('Verifying bootmode digest in PCR0 in normal mode') |
| self.check_state((self.checkers.crossystem_checker, { |
| 'devsw_boot': '0', |
| 'mainfw_type': 'normal' |
| })) |
| # dev_mode: 0, rec_mode: 0, keyblock_flags: "normal" (1) |
| if not self._check_pcr(0, hashlib.sha1(chr(0) + chr(0) + chr(1))): |
| error.TestFail('PCR0 was not extended with bootmode 0|0|1!') |
| |
| logging.info('Verifying bootmode digest in PCR0 in recovery mode') |
| self.switcher.reboot_to_mode(to_mode='rec') |
| self.check_state((self.checkers.crossystem_checker, { |
| 'devsw_boot': '0', |
| 'mainfw_type': 'recovery' |
| })) |
| # dev_mode: 0, rec_mode: 1, keyblock_flags: "unknown" (0) |
| if not self._check_pcr(0, hashlib.sha1(chr(0) + chr(1) + chr(0))): |
| error.TestFail('PCR0 was not extended with bootmode 0|1|0!') |
| |
| logging.info('Transitioning to dev mode for next test') |
| self.switcher.reboot_to_mode(to_mode='dev') |
| |
| logging.info('Verifying bootmode digest in PCR0 in developer mode') |
| self.check_state((self.checkers.crossystem_checker, { |
| 'devsw_boot': '1', |
| 'mainfw_type': 'developer' |
| })) |
| # dev_mode: 1, rec_mode: 0, keyblock_flags: "normal" (1) |
| if not self._check_pcr(0, hashlib.sha1(chr(1) + chr(0) + chr(1))): |
| error.TestFail('PCR0 was not extended with bootmode 1|0|1!') |
| |
| logging.info('Verifying bootmode digest in PCR0 in dev-recovery mode') |
| self.switcher.reboot_to_mode(to_mode='rec') |
| self.check_state((self.checkers.crossystem_checker, { |
| 'devsw_boot': '1', |
| 'mainfw_type': 'recovery' |
| })) |
| # dev_mode: 1, rec_mode: 1, keyblock_flags: "unknown" (0) |
| if not self._check_pcr(0, hashlib.sha1(chr(1) + chr(1) + chr(0))): |
| error.TestFail('PCR0 was not extended with bootmode 1|1|0!') |
| |
| logging.info('All done, returning to normal mode') |
| self.switcher.reboot_to_mode(to_mode='normal') |