vector-uefi/fd/tool/chipsec/modules/common/smrr.py
#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)
#
# 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()