mirror of
https://github.com/chipsec/chipsec
synced 2026-06-08 13:31:00 +00:00
9f13a489ae
Signed-off-by: Sae86 <sara.batllori@intel.com>
194 lines
6.8 KiB
Python
194 lines
6.8 KiB
Python
# CHIPSEC: Platform Security Assessment Framework
|
|
# Copyright (c) 2010-2022, Intel Corporation
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; Version 2.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
#
|
|
# Contact information:
|
|
# chipsec@intel.com
|
|
#
|
|
|
|
|
|
"""
|
|
Common include file for modules
|
|
|
|
|
|
"""
|
|
|
|
import chipsec.chipset
|
|
from enum import Enum
|
|
from chipsec.defines import bit, is_set
|
|
from chipsec.logger import logger
|
|
|
|
|
|
class ModuleResult:
|
|
# -------------------------------------------------------
|
|
# Legacy results
|
|
# -------------------------------------------------------
|
|
FAILED = 0
|
|
PASSED = 1
|
|
WARNING = 2
|
|
DEPRECATED = 4
|
|
INFORMATION = 5
|
|
NOTAPPLICABLE = 6
|
|
ERROR = -1
|
|
# -------------------------------------------------------
|
|
class status(Enum):
|
|
SUCCESS = [0x0000000000000000, 'Test module completed successfully']
|
|
LOCKS = [bit(31), 'Locks are not set']
|
|
MITIGATION = [bit(30), 'Does not support mitigation']
|
|
CONFIGURATION = [bit(29), 'Configuration not valid']
|
|
PROTECTION = [bit(28), 'Protection not supported/enabled']
|
|
ACCESS_RW = [bit(27), 'Read or write access issues']
|
|
RESTORE = [bit(26), 'Cannot restore binary/value']
|
|
POTENTIALLY_VULNERABLE = [bit(25), 'Found potential vulnerabilities']
|
|
ALL_FFS = [bit(19), 'Read returned all 0xFFs']
|
|
ALL_00S = [bit(18), 'Read returned all 0x00s']
|
|
DEVICE_DISABLED = [bit(17), 'Device is disabled']
|
|
FEATURE_DISABLED = [bit(16), 'Feature is disabled']
|
|
PARSE_ERROR = [bit(15), 'Issue parsing the data']
|
|
UNDEFINED_RANGES = [bit(14), 'Memory ranges are not defined']
|
|
VERIFY = [bit(12), 'Manual verification/further testing recommended']
|
|
UNSUPPORTED_FEATURE = [bit(11), 'Feature not supported']
|
|
UNSUPPORTED_OPTION = [bit(10), 'Option not supported']
|
|
DEBUG_FEATURE = [bit(9), 'A debug feature is enabled or an unexpected debug state was discovered on this platform']
|
|
NOT_APPLICABLE = [bit(8), 'Skipping module since it is not supported']
|
|
INFORMATION = [bit(0), 'For your information']
|
|
INVALID = [0xFFFFFFFFFFFFFFFF, 'Error running the test']
|
|
|
|
def __init__(self, ID: int = 0, url: str = ''):
|
|
self._id = ID
|
|
self._url = url
|
|
self._result = 0x00000000
|
|
self._return_code = self.status.SUCCESS.value[0]
|
|
self._message = ''
|
|
self.logger = logger()
|
|
|
|
def setStatusBit(self, status) -> None:
|
|
if is_set(self._result, status.value[0]) is not True:
|
|
self._result ^= status.value[0]
|
|
self._message += ' / ' + status.value[1]
|
|
|
|
def setResultBits(self) -> None:
|
|
self._return_code ^= self._result << 32
|
|
|
|
def setTestID(self) -> None:
|
|
self._return_code ^= self._id << 4
|
|
|
|
def printLogOutput(self) -> None:
|
|
if self._result == self.status.SUCCESS.value[0]:
|
|
self.logger.log_good(f'RC 0x{self._return_code:016x}: {self.status.SUCCESS.value[1]}')
|
|
else:
|
|
self.logger.log_important(f"For next steps: {self._url}")
|
|
self.logger.log_important(f"RC 0x{self._return_code:016x}: {self._message}")
|
|
|
|
def buildReturnCode(self) -> None:
|
|
self.setResultBits()
|
|
self.setTestID()
|
|
self.printLogOutput()
|
|
|
|
def getReturnCode(self, result: int) -> int:
|
|
if chipsec.chipset.cs().using_return_codes:
|
|
self.buildReturnCode()
|
|
else:
|
|
self._return_code = result
|
|
return self._return_code
|
|
|
|
# -------------------------------------------------------
|
|
# Legacy results
|
|
# -------------------------------------------------------
|
|
result_priority = {
|
|
ModuleResult.PASSED: 0,
|
|
ModuleResult.NOTAPPLICABLE: 0,
|
|
ModuleResult.DEPRECATED: 0,
|
|
ModuleResult.INFORMATION: 1,
|
|
ModuleResult.WARNING: 2,
|
|
ModuleResult.FAILED: 3,
|
|
ModuleResult.ERROR: 4
|
|
}
|
|
|
|
ModuleResultName = {
|
|
ModuleResult.FAILED: 'Failed',
|
|
ModuleResult.PASSED: 'Passed',
|
|
ModuleResult.WARNING: 'Warning',
|
|
ModuleResult.DEPRECATED: 'Deprecated',
|
|
ModuleResult.INFORMATION: 'Information',
|
|
ModuleResult.ERROR: 'Error',
|
|
ModuleResult.NOTAPPLICABLE: 'NotApplicable'
|
|
}
|
|
|
|
def getModuleResultName(res) -> str:
|
|
if chipsec.chipset.cs().using_return_codes:
|
|
return 'Passed' if (res & 0xFFFFFFFF00000000) == 0 else 'Failed'
|
|
return ModuleResultName[res] if res in ModuleResultName else ModuleResultName[ModuleResult.ERROR]
|
|
# -------------------------------------------------------
|
|
|
|
class BaseModule:
|
|
def __init__(self):
|
|
self.cs = chipsec.chipset.cs()
|
|
self.logger = logger()
|
|
# -------------------------------------------------------
|
|
# Legacy results
|
|
# -------------------------------------------------------
|
|
self.res = ModuleResult.PASSED
|
|
# -------------------------------------------------------
|
|
|
|
def is_supported(self):
|
|
"""
|
|
This method should be overwritten by the module returning True or False
|
|
depending whether or not this module is supported in the currently running
|
|
platform.
|
|
To access the currently running platform use
|
|
"""
|
|
return True
|
|
|
|
# -------------------------------------------------------
|
|
# Legacy results
|
|
# -------------------------------------------------------
|
|
def update_res(self, value):
|
|
if value not in result_priority:
|
|
self.logger.log_verbose(f'Attempting to set invalid result status: {value}')
|
|
return
|
|
cur_priority = result_priority[self.res]
|
|
new_priority = result_priority[value]
|
|
if new_priority >= cur_priority:
|
|
self.res = value
|
|
# -------------------------------------------------------
|
|
|
|
def run(self, module_argv):
|
|
raise NotImplementedError('Sub-class should overwrite the run() method')
|
|
|
|
|
|
MTAG_BIOS = 'BIOS'
|
|
MTAG_SMM = 'SMM'
|
|
MTAG_SECUREBOOT = 'SECUREBOOT'
|
|
MTAG_HWCONFIG = 'HWCONFIG'
|
|
MTAG_CPU = 'CPU'
|
|
|
|
|
|
# ! [Available Tags]
|
|
MTAG_METAS = {
|
|
MTAG_BIOS: 'System Firmware (BIOS/UEFI) Modules',
|
|
MTAG_SMM: 'System Management Mode (SMM) Modules',
|
|
MTAG_SECUREBOOT: 'Secure Boot Modules',
|
|
MTAG_HWCONFIG: 'Hardware Configuration Modules',
|
|
MTAG_CPU: 'CPU Modules',
|
|
}
|
|
# ! [Available Tags]
|
|
MODULE_TAGS = dict([(_tag, []) for _tag in MTAG_METAS])
|
|
|
|
#
|
|
# Common module command line options
|
|
#
|
|
OPT_MODIFY = 'modify'
|