hackedteam/vector-edk

View on GitHub
vector-uefi/fd/tool/chipsec/modules/common/smrr.py

Summary

Maintainability
B
5 hrs
Test Coverage
#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()