diff --git a/source/drivers/linux/Makefile b/source/drivers/linux/Makefile index 1c1af7f9..c77c70b4 100644 --- a/source/drivers/linux/Makefile +++ b/source/drivers/linux/Makefile @@ -19,10 +19,12 @@ endif chipsec64: clean nasm -f elf64 -o amd64/cpu.o amd64/cpu.asm; make -C $(KERNEL_SRC_DIR) SUBDIRS=`pwd` modules + make -C ../../tool/chipsec/helper/linux chipsec32: clean nasm -f elf32 -o i386/cpu.o i386/cpu.asm; make -C $(KERNEL_SRC_DIR) SUBDIRS=`pwd` modules + make -C ../../tool/chipsec/helper/linux install: ./run.sh diff --git a/source/tool/chipsec/modules/common/ia32cfg.py b/source/tool/chipsec/modules/common/ia32cfg.py new file mode 100644 index 00000000..15e7b802 --- /dev/null +++ b/source/tool/chipsec/modules/common/ia32cfg.py @@ -0,0 +1,66 @@ +#CHIPSEC: Platform Security Assessment Framework +#Copyright (c) 2010-2016, 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 +# + +""" + +Tests that IA-32/IA-64 architectural features are configured and locked, including IA32 Model Specific Registers (MSRs) + +Reference: Intel Software Developer's Manual + +""" + +from chipsec.module_common import * + + +TAGS = [MTAG_HWCONFIG] + +class ia32cfg(BaseModule): + def __init__(self): + BaseModule.__init__(self) + self.res = ModuleResult.PASSED + + def is_supported(self): + if self.cs.is_atom(): return False + else: return True + + def check_ia32feature_control(self): + self.logger.start_test( "IA32 Feature Control Lock" ) + self.logger.log( "[*] Verifying IA32_Feature_Control MSR is locked on all logical CPUs.." ) + + ok = True + for tid in range(self.cs.msr.get_cpu_thread_count()): + #feature_cntl = chipsec.chipset.read_register( self.cs, 'IA32_FEATURE_CONTROL', tid ) + #chipsec.chipset.print_register( self.cs, 'IA32_FEATURE_CONTROL', feature_cntl ) + feature_cntl_lock = chipsec.chipset.get_control( self.cs, 'Ia32FeatureControlLock' ) + self.logger.log( "[*] cpu%d: IA32_Feature_Control Lock = %d" % (tid,feature_cntl_lock) ) + if 0 == feature_cntl_lock: ok = False + + if ok: + self.res = ModuleResult.PASSED + self.logger.log_passed_check( "IA32_FEATURE_CONTROL MSR is locked on all logical CPUs" ) + else: + self.res = ModuleResult.FAILED + self.logger.log_failed_check( "IA32_FEATURE_CONTROL MSR is not locked on all logical CPUs" ) + + return self.res + + def run(self, module_argv): + return self.check_ia32feature_control() + \ No newline at end of file diff --git a/source/tool/chipsec/modules/common/rtclock.py b/source/tool/chipsec/modules/common/rtclock.py new file mode 100644 index 00000000..10421d26 --- /dev/null +++ b/source/tool/chipsec/modules/common/rtclock.py @@ -0,0 +1,66 @@ +#CHIPSEC: Platform Security Assessment Framework +#Copyright (c) 2010-2016, 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 +# + +""" +Checks for RTC memory locks. Since we do not know what RTC memory will be used for on a specific platform, we return WARNING (rather than FAILED) if the memory is not locked. +""" + +from chipsec.module_common import * + +TAGS = [MTAG_BIOS,MTAG_HWCONFIG] + + +class rtclock(BaseModule): + + def __init__(self): + BaseModule.__init__(self) + self.res = ModuleResult.PASSED + + def is_supported(self): + return (self.cs.get_chipset_id() in chipsec.chipset.CHIPSET_FAMILY_CORE) + + def check_rtclock(self): + self.logger.start_test( "Protected RTC memory locations" ) + + rc_reg = chipsec.chipset.read_register( self.cs, 'RC' ) + chipsec.chipset.print_register( self.cs, 'RC', rc_reg ) + ll = chipsec.chipset.get_register_field( self.cs, 'RC', rc_reg, 'LL' ) + ul = chipsec.chipset.get_register_field( self.cs, 'RC', rc_reg, 'UL' ) + + if ll == 1: self.logger.log_good( "Protected bytes (0x38-0x3F) in low 128-byte bank of RTC memory are locked" ) + else: self.logger.log_bad( "Protected bytes (0x38-0x3F) in low 128-byte bank of RTC memory are not locked" ) + if ul == 1: self.logger.log_good( "Protected bytes (0x38-0x3F) in high 128-byte bank of RTC memory are locked" ) + else: self.logger.log_bad( "Protected bytes (0x38-0x3F) in high 128-byte bank of RTC memory are not locked" ) + + if ll == 1 and ul == 1: + self.res = ModuleResult.PASSED + self.logger.log_passed_check( "Protected locations in RTC memory are locked" ) + else: + self.res = ModuleResult.WARNING + self.logger.log_warn_check( "Protected locations in RTC memory are accessible (BIOS may not be using them)" ) + + return self.res + + # -------------------------------------------------------------------------- + # run( module_argv ) + # Required function: run here all tests from this module + # -------------------------------------------------------------------------- + def run( self, module_argv ): + return self.check_rtclock() diff --git a/source/tool/chipsec/modules/common/spi_fdopss.py b/source/tool/chipsec/modules/common/spi_fdopss.py new file mode 100644 index 00000000..e9ac941c --- /dev/null +++ b/source/tool/chipsec/modules/common/spi_fdopss.py @@ -0,0 +1,59 @@ +#CHIPSEC: Platform Security Assessment Framework +#Copyright (c) 2010-2016, 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 +# + +""" +Checks for SPI Controller Flash Descriptor Security Override Pin Strap (FDOPSS). On some systems, this may be routed to a jumper on the motherboard. +""" + +from chipsec.module_common import * +TAGS = [MTAG_BIOS] + +class spi_fdopss(BaseModule): + + def __init__(self): + BaseModule.__init__(self) + + def is_supported(self): + return True + + def check_fd_security_override_strap(self): + self.logger.start_test( "SPI Flash Descriptor Security Override Pin-Strap" ) + + if not chipsec.chipset.is_register_defined( self.cs, 'HSFS' ): + self.logger.error( "Couldn't find definition of required configuration registers (HSFS)" ) + return ModuleResult.ERROR + + hsfs_reg = chipsec.chipset.read_register( self.cs, 'HSFS' ) + chipsec.chipset.print_register( self.cs, 'HSFS', hsfs_reg ) + fdopss = chipsec.chipset.get_register_field( self.cs, 'HSFS', hsfs_reg, 'FDOPSS' ) + + if 0 != fdopss: + self.logger.log_passed_check( "SPI Flash Descriptor Security Override is disabled" ) + return ModuleResult.PASSED + else: + self.logger.log_failed_check( "SPI Flash Descriptor Security Override is enabled" ) + return ModuleResult.FAILED + + # -------------------------------------------------------------------------- + # run( module_argv ) + # Required function: run here all tests from this module + # -------------------------------------------------------------------------- + def run( self, module_argv ): + return self.check_fd_security_override_strap() diff --git a/source/tool/chipsec/modules/memconfig.py b/source/tool/chipsec/modules/memconfig.py new file mode 100644 index 00000000..880ab468 --- /dev/null +++ b/source/tool/chipsec/modules/memconfig.py @@ -0,0 +1,96 @@ +#CHIPSEC: Platform Security Assessment Framework +#Copyright (c) 2010-2015, 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 +# + + +""" +This module verifies memory map secure configuration, +i.e. that memory map registers are correctly configured and locked down. +""" + +from chipsec.module_common import * + +_MODULE_NAME = 'memconfig' + +TAGS = [MTAG_HWCONFIG] + + +memmap_registers = { + "PCI0.0.0_GGC" : 'GGCLOCK', + "PCI0.0.0_PAVPC" : 'PAVPLCK', + "PCI0.0.0_DPR" : 'LOCK', + "PCI0.0.0_MESEG_MASK" : 'MELCK', + "PCI0.0.0_REMAPBASE" : 'LOCK', + "PCI0.0.0_REMAPLIMIT" : 'LOCK', + "PCI0.0.0_TOM" : 'LOCK', + "PCI0.0.0_TOUUD" : 'LOCK', + "PCI0.0.0_BDSM" : 'LOCK', + "PCI0.0.0_BGSM" : 'LOCK', + "PCI0.0.0_TSEGMB" : 'LOCK', + "PCI0.0.0_TOLUD" : 'LOCK' +} + +memmap_registers_dev0bars = [ + "PCI0.0.0_PXPEPBAR", + "PCI0.0.0_MCHBAR", + "PCI0.0.0_PCIEXBAR", + "PCI0.0.0_DMIBAR", +] + + +class memconfig(BaseModule): + + def __init__(self): + BaseModule.__init__(self) + + def is_supported(self): + return self.cs.is_core() + + def check_memmap_locks(self): + self.logger.start_test( "Host Bridge Memory Map Locks" ) + + regs = memmap_registers.keys() + regs.sort() + all_locked = True + + for r in regs: + d = chipsec.chipset.get_register_def( self.cs, r ) + v = chipsec.chipset.read_register( self.cs, r ) + locked = chipsec.chipset.get_register_field( self.cs, r, v, memmap_registers[r] ) + if locked == 1: + self.logger.log_good( "%-20s = 0x%016X - LOCKED - %s" % (r, v, d['desc']) ) + else: + all_locked = False + self.logger.log_bad( "%-20s = 0x%016X - UNLOCKED - %s" % (r, v, d['desc']) ) + + if all_locked: + res = ModuleResult.PASSED + self.logger.log_passed_check( "All memory map registers seem to be locked down" ) + else: + res = ModuleResult.FAILED + self.logger.log_failed_check( "Not all memory map registers are locked down" ) + + return res + + # -------------------------------------------------------------------------- + # run( module_argv ) + # Required function: run here all tests from this module + # -------------------------------------------------------------------------- + def run( self, module_argv ): + return self.check_memmap_locks() diff --git a/source/tool/chipsec/modules/tools/cpu/sinkhole.py b/source/tool/chipsec/modules/tools/cpu/sinkhole.py new file mode 100644 index 00000000..7cc34da7 --- /dev/null +++ b/source/tool/chipsec/modules/tools/cpu/sinkhole.py @@ -0,0 +1,106 @@ +#CHIPSEC: Platform Security Assessment Framework +#Copyright (c) 2010-2016, 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 +# + +""" +This module checks if CPU is affected by 'The SMM memory sinkhole' vulnerability by Christopher Domas + +NOTE: The system may hang when running this test. In that case, the mitigation to this issue is likely working but we may not be handling the exception generated. + +References: +The Memory Sinkhole `(presentation) `_, `(whitepaper) `_ by Christopher Domas +""" + +from chipsec.module_common import * +import chipsec.hal.cpu +import chipsec.helper.oshelper + +TAGS = [MTAG_SMM] + +class sinkhole(BaseModule): + + def __init__(self): + BaseModule.__init__(self) + self._cpu = chipsec.hal.cpu.CPU( self.cs ) + + + def is_supported(self): + # @TODO: Currently this module doesn't work properly on (U)EFI + return (self.cs.helper.is_windows() or self.cs.helper.is_linux()) + + def check_LAPIC_SMRR_overlap( self ): + if not chipsec.chipset.is_register_defined( self.cs, 'IA32_APIC_BASE' ) or \ + not chipsec.chipset.is_register_defined( self.cs, 'IA32_SMRR_PHYSBASE' ) or \ + not chipsec.chipset.is_register_defined( self.cs, 'IA32_SMRR_PHYSMASK' ): + self.logger.error( "Couldn't find definition of required configuration registers" ) + return ModuleResult.ERROR + + if self._cpu.check_SMRR_supported(): + self.logger.log_good( "SMRR range protection is supported" ) + else: + self.logger.log_skipped_check("CPU does not support SMRR range protection of SMRAM") + return ModuleResult.SKIPPED + + smrr_physbase_msr = chipsec.chipset.read_register( self.cs, 'IA32_SMRR_PHYSBASE', 0 ) + apic_base_msr = chipsec.chipset.read_register( self.cs, 'IA32_APIC_BASE', 0 ) + chipsec.chipset.print_register( self.cs, 'IA32_APIC_BASE', apic_base_msr ) + chipsec.chipset.print_register( self.cs, 'IA32_SMRR_PHYSBASE', smrr_physbase_msr ) + + smrrbase = chipsec.chipset.get_register_field( self.cs, 'IA32_SMRR_PHYSBASE', smrr_physbase_msr, 'PhysBase' ) + smrr_base = chipsec.chipset.get_register_field( self.cs, 'IA32_SMRR_PHYSBASE', smrr_physbase_msr, 'PhysBase', True ) + apicbase = chipsec.chipset.get_register_field( self.cs, 'IA32_APIC_BASE', apic_base_msr, 'APICBase' ) + apic_base = chipsec.chipset.get_register_field( self.cs, 'IA32_APIC_BASE', apic_base_msr, 'APICBase', True ) + + self.logger.log( "[*] Local APIC Base: 0x%016X" % apic_base ) + self.logger.log( "[*] SMRR Base : 0x%016X" % smrr_base ) + + self.logger.log( "[*] Attempting to overlap Local APIC page with SMRR region" ) + self.logger.log( "NOTE: The system may hang or process may crash when running this test. In that case, the mitigation to this issue is likely working but we may not be handling the exception generated.") + self.logger.log( " writing 0x%X to IA32_APIC_BASE[APICBase].." % smrrbase ) + try: + chipsec.chipset.write_register_field( self.cs, 'IA32_APIC_BASE', 'APICBase', smrrbase, preserve_field_position=False, cpu_thread=0 ) + ex = False + self.logger.log_bad( "Was able to modify IA32_APIC_BASE" ) + except chipsec.helper.oshelper.HWAccessViolationError: + ex = True + self.logger.log_good( "Could not modify IA32_APIC_BASE" ) + + apic_base_msr_new = chipsec.chipset.read_register( self.cs, 'IA32_APIC_BASE', 0 ) + self.logger.log( "[*] new IA32_APIC_BASE: 0x%016X" % apic_base_msr_new ) + #chipsec.chipset.print_register( self.cs, 'IA32_APIC_BASE', apic_base_msr_new ) + + if apic_base_msr_new == apic_base_msr and ex: + res = ModuleResult.PASSED + self.logger.log_passed_check( "CPU does not seem to have SMM memory sinkhole vulnerability" ) + else: + chipsec.chipset.write_register( self.cs, 'IA32_APIC_BASE', apic_base_msr, 0 ) + self.logger.log( "[*] Restored original value 0x%016X" % apic_base_msr ) + res = ModuleResult.FAILED + self.logger.log_failed_check( "CPU is succeptible to SMM memory sinkhole vulnerability" ) + + return res + + # -------------------------------------------------------------------------- + # run( module_argv ) + # Required function: run here all tests from this module + # -------------------------------------------------------------------------- + def run( self, module_argv ): + self.logger.start_test( "x86 SMM Memory Sinkhole" ) + return self.check_LAPIC_SMRR_overlap() + \ No newline at end of file