mirror of
https://github.com/chipsec/chipsec
synced 2026-06-08 13:31:00 +00:00
146 lines
6.5 KiB
Python
146 lines
6.5 KiB
Python
#CHIPSEC: Platform Security Assessment Framework
|
|
#Copyright (c) 2018, Eclypsium, Inc.
|
|
#Copyright (c) 2018, 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
|
|
|
|
The module returns the following results:
|
|
FAILED : Any one of the debug features is enabled or unlocked.
|
|
PASSED : All debug feature are diabled and locked.
|
|
|
|
Hardware 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 *
|
|
import chipsec.chipset
|
|
import chipsec.defines
|
|
_MODULE_NAME = 'debugenabled'
|
|
|
|
|
|
import chipsec.hal.uefi
|
|
import chipsec.hal.uefi_common
|
|
|
|
EDX_ENABLE_STATE = 0x00000000
|
|
IA32_DEBUG_INTERFACE_MSR = 0xC80
|
|
P2SB_DCI_PORT_ID = 0xB8
|
|
DCI_CONTROL_REG_OFFSET = 0x4
|
|
|
|
HDCIEN_MASK = 0b00000000000000000000000000010000
|
|
IA32_DEBUG_INTERFACE_DEBUGENABLE_MASK = 0b00000000000000000000000000000001
|
|
IA32_DEBUG_INTERFACE_DEBUGELOCK_MASK = 0b01000000000000000000000000000000
|
|
IA32_DEBUG_INTERFACE_DEBUGEOCCURED_MASK = 0b10000000000000000000000000000000
|
|
|
|
CPUID_IA32_DEBUG_INTERFACE_SUPPORTED_BIT11_MASK = 0b00000000000000000000100000000000
|
|
|
|
########################################################################################################
|
|
#
|
|
# Main module functionality
|
|
#
|
|
########################################################################################################
|
|
|
|
class debugenabled(chipsec.module_common.BaseModule):
|
|
|
|
|
|
|
|
def __init__(self):
|
|
BaseModule.__init__(self)
|
|
|
|
def is_supported(self):
|
|
(eax, ebx, ecx, edx) = self.cs.helper.cpuid( 1, 0 )
|
|
supported = (ecx & CPUID_IA32_DEBUG_INTERFACE_SUPPORTED_BIT11_MASK == CPUID_IA32_DEBUG_INTERFACE_SUPPORTED_BIT11_MASK)
|
|
if not supported: self.logger.log_skipped_check('CPU Debug features are not supported on this platform')
|
|
return supported
|
|
|
|
|
|
def check_dci( self ):
|
|
TestFail = ModuleResult.PASSED
|
|
self.logger.log('[X] Checking DCI register status')
|
|
value = self.cs.msgbus.mm_msgbus_reg_read(P2SB_DCI_PORT_ID,DCI_CONTROL_REG_OFFSET)
|
|
if self.logger.VERBOSE: self.logger.log('[*] DCI Control Register = 0x%X' % value )
|
|
HDCIEN = ((value & HDCIEN_MASK) == HDCIEN_MASK)
|
|
if HDCIEN:
|
|
TestFail = ModuleResult.FAILED
|
|
return TestFail
|
|
|
|
def check_cpu_debug_enable( self ):
|
|
self.logger.log('[X] Checking IA32_DEBUG_INTERFACE msr status')
|
|
TestFail = ModuleResult.PASSED
|
|
for tid in range(self.cs.msr.get_cpu_thread_count()):
|
|
(eax, edx) = self.cs.helper.read_msr( tid, IA32_DEBUG_INTERFACE_MSR )
|
|
if self.logger.VERBOSE: self.logger.log('[cpu%d] RDMSR( 0x%x ): EAX = 0x%08X, EDX = 0x%08X' % (tid, IA32_DEBUG_INTERFACE_MSR, eax, edx) )
|
|
IA32_DEBUG_INTERFACE_DEBUGENABLE = ((IA32_DEBUG_INTERFACE_DEBUGENABLE_MASK & eax) == IA32_DEBUG_INTERFACE_DEBUGENABLE_MASK)
|
|
IA32_DEBUG_INTERFACE_DEBUGELOCK = not ((IA32_DEBUG_INTERFACE_DEBUGELOCK_MASK & eax) == IA32_DEBUG_INTERFACE_DEBUGELOCK_MASK)
|
|
IA32_DEBUG_INTERFACE_DEBUGEOCCURED = ((IA32_DEBUG_INTERFACE_DEBUGEOCCURED_MASK & eax) == IA32_DEBUG_INTERFACE_DEBUGEOCCURED_MASK)
|
|
if edx == EDX_ENABLE_STATE: #Sanity check only EAX matters
|
|
if (IA32_DEBUG_INTERFACE_DEBUGENABLE) or (IA32_DEBUG_INTERFACE_DEBUGELOCK):
|
|
if self.logger.VERBOSE:
|
|
self.logger.log('IA32_DEBUG_INTERFACE_DEBUGENABLE ==' + str(IA32_DEBUG_INTERFACE_DEBUGENABLE))
|
|
self.logger.log('IA32_DEBUG_INTERFACE_DEBUGELOCK ==' + str(IA32_DEBUG_INTERFACE_DEBUGELOCK))
|
|
self.logger.log('IA32_DEBUG_INTERFACE_DEBUGEOCCURED ==' + str(IA32_DEBUG_INTERFACE_DEBUGEOCCURED))
|
|
TestFail = ModuleResult.FAILED
|
|
if IA32_DEBUG_INTERFACE_DEBUGEOCCURED:
|
|
TestFail = ModuleResult.WARNING
|
|
return TestFail
|
|
|
|
def run( self, module_argv ):
|
|
if len(module_argv) > 2:
|
|
self.logger.error('Not expecting any arguments')
|
|
return ModuleResult.ERROR
|
|
returned_result = ModuleResult.PASSED
|
|
self.logger.start_test('Debug features test')
|
|
script_pa = None
|
|
dci_test_fail = ModuleResult.PASSED
|
|
cpu_debug_test_fail = ModuleResult.PASSED
|
|
|
|
cpu_debug_test_fail = self.check_cpu_debug_enable()
|
|
if (cpu_debug_test_fail == ModuleResult.FAILED):
|
|
self.logger.log_bad('CPU IA32_DEBUG_INTERFACE is enabled')
|
|
elif cpu_debug_test_fail == ModuleResult.WARNING:
|
|
self.logger.log_warning('Debug Occured bit set in IA32_DEBUG_INTERFACE msr')
|
|
else:
|
|
self.logger.log_good('CPU IA32_DEBUG_INTERFACE is disabled')
|
|
|
|
current_platform_id = self.cs.get_chipset_id()
|
|
dci_supported = (current_platform_id == chipsec.chipset.CHIPSET_ID_CFL) or (current_platform_id == chipsec.chipset.CHIPSET_ID_KBL) or (current_platform_id == chipsec.chipset.CHIPSET_ID_SKL)
|
|
if (dci_supported):
|
|
dci_test_fail = self.check_dci()
|
|
if (dci_test_fail == ModuleResult.FAILED):
|
|
self.logger.log_bad('DCI Debug is enabled')
|
|
else:
|
|
self.logger.log_good('DCI Debug is disabled')
|
|
|
|
if (dci_test_fail == ModuleResult.FAILED or cpu_debug_test_fail == ModuleResult.FAILED):
|
|
self.logger.log_failed_check('One or more of the debug checks have failed and a debug feature is enabled')
|
|
returned_result = ModuleResult.FAILED
|
|
elif (dci_test_fail == ModuleResult.WARNING or cpu_debug_test_fail == ModuleResult.WARNING):
|
|
self.logger.log_warn_check('An unexpected debug state was discovered on this platform')
|
|
returned_result = ModuleResult.WARNING
|
|
else:
|
|
self.logger.log_passed_check('All checks have successfully passed')
|
|
returned_result = ModuleResult.PASSED
|
|
|
|
return returned_result
|