Source code for testcases.TrustedBoot
#!/usr/bin/env python3
# OpenPOWER Automated Test Project
#
# Contributors Listed Below - COPYRIGHT 2017
# [+] International Business Machines Corp.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing
# permissions and limitations under the License.
#
'''
Trustedboot IPL Tests
---------------------
This tests expect a TPM chip to be installed/removed on the system
and also a secureboot mode enabled/disabled accordingly.
If TPM chip is installed --> provide --trusted-mode in command line
If secureboot is enabled --> provide --secure-mode in command line
The "TPM Required" policy means:
enabled:
Node must have at least 1 functional TPM to boot, otherwise system will terminate
disabled:
Node can boot without a functional TPM
If system has a working TPM, the policy is a don't care. If secure mode is not enabled, the policy is a don't care.
if you set policy to "enabled" and remove/inject error on TPM -and- system is in secure mode, system boot will terminate
if you set policy to disable and remove/inject error on the TPM -and- system is in secure mode, system will still boot
'''
import unittest
import pexpect
import OpTestConfiguration
from common.OpTestSystem import OpSystemState
from common.OpTestConstants import OpTestConstants as BMC_CONST
from common.Exceptions import CommandFailed
import logging
import OpTestLogger
log = OpTestLogger.optest_logger_glob.get_logger(__name__)
[docs]class TrustedBoot(unittest.TestCase):
[docs] def setUp(self):
conf = OpTestConfiguration.conf
self.cv_SYSTEM = conf.system()
self.cv_BMC = conf.bmc()
self.cv_REST = self.cv_BMC.get_rest_api()
self.cv_HOST = conf.host()
self.cv_IPMI = conf.ipmi()
self.bmc_type = conf.args.bmc_type
self.trustedmode = conf.args.trusted_mode
self.tpm_policy = True
self.securemode = conf.args.secure_mode
def wait_for_system_shutdown(self):
raw_pty = self.cv_SYSTEM.console.get_console()
raw_pty.expect("System shutting down with error status", timeout=100)
raw_pty.expect("RC_TPM_NOFUNCTIONALTPM_FAIL", timeout=50)
raw_pty.expect(
"================================================", timeout=20)
def verify_opal_tb(self):
c = self.cv_SYSTEM.console
self.cpu = ''.join(c.run_command(
"grep '^cpu' /proc/cpuinfo |uniq|sed -e 's/^.*: //;s/[,]* .*//;'"))
log.debug(self.cpu)
if self.cpu in ["POWER9", "POWER9P"]:
part_list = ["CAPP", "IMA_CATALOG", "BOOTKERNEL", "VERSION"]
elif self.cpu in ["POWER8"]:
part_list = ["CAPP", "BOOTKERNEL"]
else:
self.skipTest("OPAL TB test not supported on %s" % self.cpu)
data = " ".join(c.run_command(
"cat /sys/firmware/opal/msglog | grep -i stb"))
if self.trustedmode:
if not "trusted mode on" in data:
self.assertTrue(False, "OPAL: trusted mode is detected as OFF")
else:
if not "trusted mode off" in data:
self.assertTrue(False, "OPAL: trusted mode is detected as ON")
return
for part in part_list:
msg = "STB: %s hash calculated" % part
if not msg in data:
self.assertTrue(False, "OPAL: %s hash not calculated" % part)
msg = "STB: %s measured on pcr" % part
if not msg in data:
self.assertTrue(
False, "OPAL: %s hash not measured on TPM PCR register" % part)
msg = "STB: EV_SEPARATOR measured on pcr"
if not msg in data:
self.assertTrue(
False, "OPAL: EV_SEPARATOR measured on TPM PCR registers")
def verify_dt_tb(self):
c = self.cv_SYSTEM.console
c.run_command("lsprop /proc/device-tree/ibm,secureboot")
if not self.trustedmode:
return
c.run_command(
"ls --color=never /proc/device-tree/ibm,secureboot/trusted-enabled")
res = c.run_command("find /proc/device-tree/ -name *tpm*")
tpm_path = res[-1]
c.run_command("lsprop %s" % tpm_path)
c.run_command("cat %s/compatible" % tpm_path)
c.run_command("cat %s/status" % tpm_path)
c.run_command("cat %s/name" % tpm_path)
c.run_command("cat %s/label" % tpm_path)
c.run_command("ls --color=never %s/linux,sml-base" % tpm_path)
c.run_command("ls --color=never %s/linux,sml-size" % tpm_path)
c.run_command("ls --color=never %s/link-id" % tpm_path)
[docs] def tearDown(self):
if self.securemode and not self.trustedmode:
self.cv_SYSTEM.sys_disable_tpm()
return
[docs]class VerifyOPALTrustedBoot(TrustedBoot):
'''
a. It verify whether OPAL measures and records of all the resources
it loads from PNOR.
b. It also verifies the corresponding DT properties for trustedboot
and TPM device.
'''
[docs] def setUp(self):
conf = OpTestConfiguration.conf
super(VerifyOPALTrustedBoot, self).setUp()
def runTest(self):
if not self.trustedmode:
return
self.cv_SYSTEM.goto_state(OpSystemState.PETITBOOT_SHELL)
self.verify_dt_tb()
self.verify_opal_tb()
[docs]class FunctionalTPM_PolicyOFF(TrustedBoot):
'''
Functional TPM, TPM Required(cleared)
- Test IPL, Measurements & event logs(Secure Mode Override jumper(s) ON or OFF)
'''
[docs] def setUp(self):
conf = OpTestConfiguration.conf
super(FunctionalTPM_PolicyOFF, self).setUp()
def runTest(self):
if not self.trustedmode:
self.skipTest(
"This test needs a functional TPM installed on system")
self.cv_SYSTEM.goto_state(OpSystemState.OFF)
self.cv_SYSTEM.sys_disable_tpm()
self.assertFalse(self.cv_SYSTEM.sys_is_tpm_enabled(),
"BMC failed to disable TPM policy")
self.tpm_policy = False
self.cv_SYSTEM.goto_state(OpSystemState.PETITBOOT_SHELL)
self.verify_dt_tb()
self.verify_opal_tb()
[docs]class FunctionalTPM_PolicyON(TrustedBoot):
'''
Functional TPM, TPM Required(set)
- Test IPL, Measurements & event logs(Secure Mode Override jumper(s) can be ON or OFF)
'''
[docs] def setUp(self):
conf = OpTestConfiguration.conf
super(FunctionalTPM_PolicyON, self).setUp()
def runTest(self):
if not self.trustedmode:
self.skipTest(
"This test needs a functional TPM installed on system")
self.cv_SYSTEM.goto_state(OpSystemState.OFF)
self.cv_SYSTEM.sys_enable_tpm()
self.assertTrue(self.cv_SYSTEM.sys_is_tpm_enabled(),
"BMC failed to enable TPM policy")
self.cv_SYSTEM.goto_state(OpSystemState.PETITBOOT_SHELL)
self.verify_dt_tb()
self.verify_opal_tb()
[docs]class NoFunctionalTPM_PolicyOFF(TrustedBoot):
'''
No Functional TPM, TPM Required(cleared)
- Test IPL, Measurements & event logs(Secure Mode Override jumper(s) can be ON or OFF)
'''
[docs] def setUp(self):
conf = OpTestConfiguration.conf
super(NoFunctionalTPM_PolicyOFF, self).setUp()
def runTest(self):
if self.trustedmode:
self.skipTest(
"This test needs a functional TPM removed from system")
self.cv_SYSTEM.goto_state(OpSystemState.OFF)
self.cv_SYSTEM.sys_disable_tpm()
self.assertFalse(self.cv_SYSTEM.sys_is_tpm_enabled(),
"BMC failed to disable TPM setting policy")
self.tpm_policy = False
self.cv_SYSTEM.goto_state(OpSystemState.PETITBOOT_SHELL)
self.verify_dt_tb()
self.verify_opal_tb()
[docs]class NoFunctionalTPM_PolicyON(TrustedBoot):
'''
No Functional TPM, TPM Required(set)
- Test IPL, Measurements & event logs(Secure Mode Override jumper(s) can be ON or OFF)
'''
[docs] def setUp(self):
conf = OpTestConfiguration.conf
super(NoFunctionalTPM_PolicyON, self).setUp()
def runTest(self):
if self.trustedmode:
self.skipTest(
"This test needs a functional TPM removed from system")
self.cv_SYSTEM.goto_state(OpSystemState.OFF)
self.cv_SYSTEM.sys_enable_tpm()
self.assertTrue(self.cv_SYSTEM.sys_is_tpm_enabled(),
"BMC failed to enable TPM policy")
if self.securemode:
self.cv_SYSTEM.sys_power_on()
self.wait_for_system_shutdown()
self.cv_SYSTEM.set_state(OpSystemState.UNKNOWN_BAD)
self.cv_SYSTEM.goto_state(OpSystemState.OFF)
self.cv_SYSTEM.sys_disable_tpm()
self.cv_SYSTEM.goto_state(OpSystemState.PETITBOOT_SHELL)
self.verify_dt_tb()
self.verify_opal_tb()
def trustedboot_suite():
s = unittest.TestSuite()
s.addTest(VerifyOPALTrustedBoot())
s.addTest(FunctionalTPM_PolicyOFF())
s.addTest(FunctionalTPM_PolicyON())
s.addTest(NoFunctionalTPM_PolicyOFF())
s.addTest(NoFunctionalTPM_PolicyON())
return s