mirror of
https://github.com/chipsec/chipsec
synced 2026-06-08 13:31:00 +00:00
161 lines
6.9 KiB
Python
161 lines
6.9 KiB
Python
#CHIPSEC: Platform Security Assessment Framework
|
|
#Copyright (c) 2010-2014, 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
|
|
#
|
|
|
|
|
|
|
|
|
|
## \addtogroup modules
|
|
# __chipsec/modules/common/smrr.py__ - checks for SMRR secure configuration to protect from SMRAM cache attack
|
|
#
|
|
|
|
|
|
from chipsec.module_common import *
|
|
TAGS = [MTAG_BIOS,MTAG_SMM]
|
|
|
|
from chipsec.hal.msr import *
|
|
|
|
|
|
# ############################################################
|
|
# SPECIFY PLATFORMS THIS MODULE IS APPLICABLE TO
|
|
# ############################################################
|
|
|
|
|
|
class smrr(BaseModule):
|
|
|
|
def __init__(self):
|
|
BaseModule.__init__(self)
|
|
|
|
def is_supported(self):
|
|
return True
|
|
|
|
#
|
|
# Check that SMRR are supported by CPU in IA32_MTRRCAP_MSR[SMRR]
|
|
#
|
|
def check_SMRR_supported(self):
|
|
(eax, edx) = self.cs.msr.read_msr( 0, self.cs.Cfg.IA32_MTRRCAP_MSR )
|
|
if self.logger.VERBOSE:
|
|
self.logger.log( "[*] IA32_MTRRCAP_MSR = 0x%08X%08X" % (edx, eax) )
|
|
self.logger.log( " SMRR = %u" % ((eax&self.cs.Cfg.IA32_MTRRCAP_SMRR_MASK)>>11) )
|
|
return (eax & self.cs.Cfg.IA32_MTRRCAP_SMRR_MASK)
|
|
|
|
def check_SMRR(self):
|
|
self.logger.start_test( "CPU SMM Cache Poisoning / SMM Range Registers (SMRR)" )
|
|
if self.check_SMRR_supported():
|
|
self.logger.log_good( "OK. SMRR are supported in IA32_MTRRCAP_MSR" )
|
|
else:
|
|
self.logger.log_important( "CPU does not support SMRR protection of SMRAM" )
|
|
self.logger.log_skipped_check("CPU does not support SMRR protection of SMRAM")
|
|
return ModuleResult.SKIPPED
|
|
|
|
#
|
|
# SMRR are supported
|
|
#
|
|
smrr_ok = True
|
|
|
|
#
|
|
# 2. Check SMRR_BASE is programmed correctly (on CPU0)
|
|
#
|
|
self.logger.log( '' )
|
|
self.logger.log( "[*] Checking SMRR Base programming.." )
|
|
(eax, edx) = self.cs.msr.read_msr( 0, self.cs.Cfg.IA32_SMRR_BASE_MSR )
|
|
msr_smrrbase = ((edx << 32) | eax)
|
|
smrrbase_msr = eax
|
|
smrrbase = smrrbase_msr & self.cs.Cfg.IA32_SMRR_BASE_BASE_MASK
|
|
self.logger.log( "[*] IA32_SMRR_BASE_MSR = 0x%08X%08X" % (edx, eax) )
|
|
self.logger.log( " BASE = 0x%08X" % smrrbase )
|
|
self.logger.log( " MEMTYPE = %X" % (smrrbase_msr& self.cs.Cfg.IA32_SMRR_BASE_MEMTYPE_MASK) )
|
|
|
|
if ( 0 != smrrbase ):
|
|
if ( self.cs.Cfg.MTRR_MEMTYPE_WB == smrrbase_msr & self.cs.Cfg.IA32_SMRR_BASE_MEMTYPE_MASK ): self.logger.log_good( "SMRR Memtype is WB" )
|
|
else: self.logger.log_important( "SMRR Memtype (= %X) is not WB", (smrrbase_msr & self.cs.Cfg.IA32_SMRR_BASE_MEMTYPE_MASK) )
|
|
else:
|
|
smrr_ok = False
|
|
self.logger.log_bad( "SMRR Base is not programmed" )
|
|
|
|
if smrr_ok: self.logger.log_good( "OK so far. SMRR Base is programmed" )
|
|
|
|
#
|
|
# 3. Check SMRR_MASK is programmed and SMRR are enabled (on CPU0)
|
|
#
|
|
self.logger.log( '' )
|
|
self.logger.log( "[*] Checking SMRR Mask programming.." )
|
|
(eax, edx) = self.cs.msr.read_msr( 0, self.cs.Cfg.IA32_SMRR_MASK_MSR )
|
|
msr_smrrmask = ((edx << 32) | eax)
|
|
smrrmask_msr = eax
|
|
self.logger.log( "[*] IA32_SMRR_MASK_MSR = 0x%08X%08X" % (edx, eax) )
|
|
self.logger.log( " MASK = 0x%08X" % (smrrmask_msr & self.cs.Cfg.IA32_SMRR_MASK_MASK_MASK) )
|
|
self.logger.log( " VLD = %u" % ((smrrmask_msr & self.cs.Cfg.IA32_SMRR_MASK_VLD_MASK)>>11) )
|
|
|
|
if not ( smrrmask_msr & self.cs.Cfg.IA32_SMRR_MASK_VLD_MASK and smrrmask_msr & self.cs.Cfg.IA32_SMRR_MASK_MASK_MASK ):
|
|
smrr_ok = False
|
|
self.logger.log_bad( "SMRR are not enabled in SMRR_MASK MSR" )
|
|
|
|
if smrr_ok: self.logger.log_good( "OK so far. SMRR are enabled in SMRR_MASK MSR" )
|
|
|
|
#
|
|
# 4. Verify that SMRR_BASE/MASK MSRs have the same values on all logical CPUs
|
|
#
|
|
self.logger.log( '' )
|
|
self.logger.log( "[*] Verifying that SMRR_BASE/MASK have the same values on all logical CPUs.." )
|
|
for tid in range(self.cs.msr.get_cpu_thread_count()):
|
|
(eax, edx) = self.cs.msr.read_msr( tid, self.cs.Cfg.IA32_SMRR_BASE_MSR )
|
|
msr_base = ((edx << 32) | eax)
|
|
(eax, edx) = self.cs.msr.read_msr( tid, self.cs.Cfg.IA32_SMRR_MASK_MSR )
|
|
msr_mask = ((edx << 32) | eax)
|
|
self.logger.log( "[CPU%d] SMRR_BASE = %016X, SMRR_MASK = %016X"% (tid, msr_base, msr_mask) )
|
|
if (msr_base != msr_smrrbase) or (msr_mask != msr_smrrmask):
|
|
smrr_ok = False
|
|
self.logger.log_bad( "SMRR MSRs do not match on all CPUs" )
|
|
break
|
|
|
|
if smrr_ok: self.logger.log_good( "OK so far. SMRR MSRs match on all CPUs" )
|
|
|
|
"""
|
|
Don't want invasive action in this test
|
|
#
|
|
# 5. Reading from & writing to SMRR_BASE physical address
|
|
# writes should be dropped, reads should return all F's
|
|
#
|
|
self.logger.log( "[*] Trying to read/modify memory at SMRR_BASE address 0x%08X.." % smrrbase )
|
|
smram_buf = self.cs.mem.read_physical_mem( smrrbase, 0x10 )
|
|
#self.logger.log( "Contents at 0x%08X:\n%s" % (smrrbase, repr(smram_buf.raw)) )
|
|
self.cs.mem.write_physical_mem_dword( smrrbase, 0x90909090 )
|
|
if ( 0xFFFFFFFF == self.cs.mem.read_physical_mem_dword( smrrbase ) ):
|
|
self.logger.log_good( "OK. Memory at SMRR_BASE contains all F's and is not modifiable" )
|
|
else:
|
|
smrr_ok = False
|
|
self.logger.log_bad( "Contents of memory at SMRR_BASE are modifiable" )
|
|
"""
|
|
|
|
|
|
self.logger.log( '' )
|
|
if not smrr_ok: self.logger.log_failed_check( "SMRR protection against cache attack is not configured properly" )
|
|
else: self.logger.log_passed_check( "SMRR protection against cache attack seems properly configured" )
|
|
|
|
return smrr_ok
|
|
|
|
# --------------------------------------------------------------------------
|
|
# run( module_argv )
|
|
# Required function: run here all tests from this module
|
|
# --------------------------------------------------------------------------
|
|
def run( self, module_argv ):
|
|
return self.check_SMRR()
|
|
|