Files
chipsec-chipsec/chipsec/modules/common/debugenabled.py
T
2023-10-25 16:35:28 -07:00

147 lines
6.2 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, ModuleResult
from chipsec.defines import BIT11
_MODULE_NAME = 'debugenabled'
class debugenabled(BaseModule):
def __init__(self):
BaseModule.__init__(self)
self.rc_res = ModuleResult(0xe516a56, 'https://chipsec.github.io/modules/chipsec.modules.common.debugenabled.html')
self.is_enable_set = False
self.is_debug_set = False
self.is_lock_set = True
def is_supported(self):
# 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.cpu.cpuid(1, 0)
supported = (ecx & BIT11) != 0
if not supported and not self.cs.is_register_defined('ECTRL'):
self.logger.log_important('CPU Debug features are not supported on this platform. Skipping module.')
self.rc_res.setStatusBit(self.rc_res.status.NOT_APPLICABLE)
self.res = self.rc_res.getReturnCode(ModuleResult.NOTAPPLICABLE)
return supported
def check_dci(self):
TestFail = ModuleResult.PASSED
self.logger.log('')
self.logger.log('[*] Checking DCI register status')
ectrl = self.cs.read_register('ECTRL')
HDCIEN = self.cs.get_register_field('ECTRL', ectrl, 'ENABLE') == 1
if self.logger.VERBOSE:
self.cs.print_register('ECTRL', ectrl)
if HDCIEN:
self.logger.log_bad('DCI Debug is enabled')
TestFail = ModuleResult.FAILED
self.rc_res.setStatusBit(self.rc_res.status.DEBUG_FEATURE)
else:
self.logger.log_good('DCI Debug is disabled')
return TestFail
def check_cpu_debug_enable(self):
self.logger.log('')
self.logger.log('[*] Checking IA32_DEBUG_INTERFACE MSR status')
TestFail = ModuleResult.PASSED
for tid in range(self.cs.msr.get_cpu_thread_count()):
dbgiface = self.cs.read_register('IA32_DEBUG_INTERFACE', tid)
IA32_DEBUG_INTERFACE_DEBUGENABLE = self.cs.get_register_field('IA32_DEBUG_INTERFACE', dbgiface, 'ENABLE') == 1
IA32_DEBUG_INTERFACE_DEBUGELOCK = self.cs.get_register_field('IA32_DEBUG_INTERFACE', dbgiface, 'LOCK') == 1
IA32_DEBUG_INTERFACE_DEBUGEOCCURED = self.cs.get_register_field('IA32_DEBUG_INTERFACE', dbgiface, 'DEBUG_OCCURRED') == 1
if self.logger.VERBOSE:
self.cs.print_register('IA32_DEBUG_INTERFACE', dbgiface)
if IA32_DEBUG_INTERFACE_DEBUGENABLE:
self.logger.log_bad('CPU debug enable requested by software.')
self.is_enable_set = True
TestFail = ModuleResult.FAILED
self.rc_res.setStatusBit(self.rc_res.status.DEBUG_FEATURE)
if not IA32_DEBUG_INTERFACE_DEBUGELOCK:
self.logger.log_bad('CPU debug interface is not locked.')
self.is_lock_set = False
TestFail = ModuleResult.FAILED
self.rc_res.setStatusBit(self.rc_res.status.LOCKS)
if IA32_DEBUG_INTERFACE_DEBUGEOCCURED:
self.logger.log_important('Debug Occurred bit set in IA32_DEBUG_INTERFACE MSR')
self.is_debug_set = True
self.rc_res.setStatusBit(self.rc_res.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):
self.logger.start_test('Debug features test')
cpu_debug_test_fail = self.check_cpu_debug_enable()
dci_test_fail = ModuleResult.PASSED
if self.cs.is_register_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 (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.rc_res.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.rc_res.getReturnCode(ModuleResult.WARNING)
else:
self.logger.log_passed('All checks have successfully passed')
return self.res