mirror of
https://github.com/chipsec/chipsec
synced 2026-06-08 13:31:00 +00:00
32aed148dd
Signed-off-by: Nathaniel Mitchell <nathaniel.p.mitchell@intel.com>
168 lines
6.9 KiB
Python
168 lines
6.9 KiB
Python
# CHIPSEC: Platform Security Assessment Framework
|
|
# Copyright (c) 2018, Eclypsium, Inc.
|
|
# Copyright (c) 2018-2021, 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.
|
|
#
|
|
|
|
"""
|
|
This module checks if the system has debug features turned on,
|
|
specifically the Direct Connect Interface (DCI).
|
|
|
|
This module checks the following bits:
|
|
1. HDCIEN bit in the DCI Control Register
|
|
2. Debug enable bit in the IA32_DEBUG_INTERFACE MSR
|
|
3. Debug lock bit in the IA32_DEBUG_INTERFACE MSR
|
|
4. Debug occurred bit in the IA32_DEBUG_INTERFACE MSR
|
|
|
|
Usage:
|
|
``chipsec_main -m common.debugenabled``
|
|
|
|
Examples:
|
|
>>> chipsec_main.py -m common.debugenabled
|
|
|
|
The module returns the following results:
|
|
- **FAILED** : Any one of the debug features is enabled or unlocked.
|
|
- **PASSED** : All debug feature are disabled and locked.
|
|
|
|
Registers used:
|
|
- IA32_DEBUG_INTERFACE[DEBUGENABLE]
|
|
- IA32_DEBUG_INTERFACE[DEBUGELOCK]
|
|
- IA32_DEBUG_INTERFACE[DEBUGEOCCURED]
|
|
- P2SB_DCI.DCI_CONTROL_REG[HDCIEN]
|
|
|
|
"""
|
|
|
|
from chipsec.module_common import BaseModule, CPU
|
|
from chipsec.library.returncode import ModuleResult
|
|
from chipsec.library.defines import BIT11
|
|
from typing import List
|
|
|
|
TAGS = [CPU]
|
|
METADATA_TAGS = ['OPENSOURCE', 'IA', 'COMMON', 'DEBUGENABLED']
|
|
|
|
_MODULE_NAME = 'debugenabled'
|
|
|
|
|
|
class debugenabled(BaseModule):
|
|
|
|
def __init__(self):
|
|
BaseModule.__init__(self)
|
|
self.cs.set_scope({
|
|
"ECTRL": "8086.DCI",
|
|
"IA32_DEBUG_INTERFACE": "8086.MSR"
|
|
})
|
|
self.is_enable_set = False
|
|
self.is_debug_set = False
|
|
self.is_lock_set = True
|
|
|
|
def is_supported(self) -> bool:
|
|
# Use CPUID Function 1 to determine if the IA32_DEBUG_INTERFACE MSR is supported.
|
|
# See IA32 SDM CPUID Instruction for details. (SDBG ECX bit 11)
|
|
(_, _, ecx, _) = self.cs.hals.cpu.cpuid(1, 0)
|
|
supported = (ecx & BIT11) != 0
|
|
if not supported and not self.cs.register.is_defined('ECTRL'):
|
|
self.logger.log_important('CPU Debug features are not supported on this platform. Skipping module.')
|
|
return supported
|
|
|
|
def check_dci(self) -> int:
|
|
TestFail = ModuleResult.PASSED
|
|
self.logger.log('')
|
|
self.logger.log('[*] Checking DCI register status')
|
|
ectrl = self.cs.register.get_list_by_name('ECTRL')
|
|
if not ectrl:
|
|
self.logger.log_important('ECTRL register not found. Skipping DCI check.')
|
|
return ModuleResult.WARNING
|
|
ectrl.read_and_verbose_print()
|
|
hdcien_mask = ectrl[0].get_field_mask('ENABLE', True)
|
|
|
|
if ectrl.is_all_field_value(ectrl[0].get_field('ENABLE'), 'ENABLE'):
|
|
self.logger.log_good('CPU debug enable is set consistently')
|
|
if ectrl.is_any_value(hdcien_mask, 'ENABLE'):
|
|
self.logger.log_bad('DCI Debug is enabled')
|
|
TestFail = ModuleResult.FAILED
|
|
self.result.setStatusBit(self.result.status.DEBUG_FEATURE)
|
|
else:
|
|
self.logger.log_good('DCI Debug is disabled')
|
|
return TestFail
|
|
|
|
def check_cpu_debug_enable(self) -> int:
|
|
self.logger.log('')
|
|
self.logger.log('[*] Checking IA32_DEBUG_INTERFACE MSR status')
|
|
TestFail = ModuleResult.PASSED
|
|
dbg_regs = self.cs.register.get_list_by_name('IA32_DEBUG_INTERFACE')
|
|
if not dbg_regs:
|
|
self.logger.log_important('IA32_DEBUG_INTERFACE MSR not found. Skipping CPU debug enable check.')
|
|
return ModuleResult.WARNING
|
|
dbg_regs.read_and_verbose_print()
|
|
|
|
|
|
if dbg_regs.is_all_field_value(dbg_regs[0].get_field('ENABLE'), 'ENABLE'):
|
|
self.logger.log_good('CPU debug enable is set consitently')
|
|
if dbg_regs.is_any_field_value(1, 'ENABLE'):
|
|
self.logger.log_bad('CPU debug enable requested by software.')
|
|
self.is_enable_set = True
|
|
TestFail = ModuleResult.FAILED
|
|
self.result.setStatusBit(self.result.status.DEBUG_FEATURE)
|
|
if dbg_regs.is_all_field_value(dbg_regs[0].get_field('LOCK'), 'LOCK'):
|
|
self.logger.log_good('CPU debug lock is set consitently')
|
|
if dbg_regs.is_any_field_value(0, 'LOCK'):
|
|
self.logger.log_bad('CPU debug interface is not locked.')
|
|
self.is_lock_set = False
|
|
TestFail = ModuleResult.FAILED
|
|
self.result.setStatusBit(self.result.status.LOCKS)
|
|
if dbg_regs.is_any_field_value(1, 'DEBUG_OCCURRED'):
|
|
self.logger.log_important('Debug Occurred bit set in IA32_DEBUG_INTERFACE MSR')
|
|
self.is_debug_set = True
|
|
self.result.setStatusBit(self.result.status.DEBUG_FEATURE)
|
|
if TestFail == ModuleResult.PASSED:
|
|
TestFail = ModuleResult.WARNING
|
|
if TestFail == ModuleResult.PASSED:
|
|
self.logger.log_good('CPU debug interface state is correct.')
|
|
return TestFail
|
|
|
|
def run(self, module_argv: List[str]) -> int:
|
|
self.logger.start_test('Debug features test')
|
|
|
|
cpu_debug_test_fail = self.check_cpu_debug_enable()
|
|
|
|
dci_test_fail = ModuleResult.PASSED
|
|
if self.cs.register.is_defined('ECTRL'):
|
|
dci_test_fail = self.check_dci()
|
|
|
|
self.logger.log('')
|
|
self.logger.log('[*] Module Results:')
|
|
|
|
if self.is_debug_set:
|
|
self.logger.log_important('IA32_DEBUG_INTERFACE.DEBUG_OCCURRED bit is set.')
|
|
if self.is_enable_set:
|
|
self.logger.log_important('IA32_DEBUG_INTERFACE.ENABLE bit is set.')
|
|
if not self.is_lock_set:
|
|
self.logger.log_important('IA32_DEBUG_INTERFACE.LOCK bit is NOT set.')
|
|
|
|
if self.cs.control.is_defined('SamplePart'):
|
|
sp = self.cs.control.get_list_by_name('SamplePart')
|
|
if sp.is_all_value(1):
|
|
self.logger.log_passed('CPU is a Sample Part. Test is N/A.')
|
|
self.res = self.result.getReturnCode(ModuleResult.INFORMATION)
|
|
return self.res
|
|
|
|
if (dci_test_fail == ModuleResult.FAILED) or (cpu_debug_test_fail == ModuleResult.FAILED):
|
|
self.logger.log_failed('One or more of the debug checks have failed and a debug feature is enabled')
|
|
self.res = self.result.getReturnCode(ModuleResult.FAILED)
|
|
elif (dci_test_fail == ModuleResult.WARNING) or (cpu_debug_test_fail == ModuleResult.WARNING):
|
|
self.logger.log_warning('An unexpected debug state was discovered on this platform')
|
|
self.res = self.result.getReturnCode(ModuleResult.WARNING)
|
|
else:
|
|
self.logger.log_passed('All checks have successfully passed')
|
|
self.res = self.result.getReturnCode(ModuleResult.PASSED)
|
|
|
|
return self.res
|