diff --git a/chipsec/modules/common/sgx_check.py b/chipsec/modules/common/sgx_check.py index 8f4d3e70..57850d44 100644 --- a/chipsec/modules/common/sgx_check.py +++ b/chipsec/modules/common/sgx_check.py @@ -1,5 +1,5 @@ #CHIPSEC: Platform Security Assessment Framework -#Copyright (c) 2010-2021, Intel Corporation +#Copyright (c) 2010-2022, Intel Corporation # #This program is free software; you can redistribute it and/or #modify it under the terms of the GNU General Public License @@ -23,12 +23,47 @@ """ Check SGX related configuration -Reference: SGX BWG, CDI/IBP#: 565432 + +Reference: + - SGX BWG, CDI/IBP#: 565432 + +Usage: + ``chipsec_main -m common.sgx_check`` + +Examples: + >>> chipsec_main.py -m common.sgx_check + +Registers used: + - IA32_FEATURE_CONTROL.SGX_GLOBAL_EN + - IA32_FEATURE_CONTROL.LOCK + - IA32_DEBUG_INTERFACE.ENABLE + - IA32_DEBUG_INTERFACE.LOCK + - MTRRCAP.PRMRR + - PRMRR_VALID_CONFIG + - PRMRR_PHYBASE.PRMRR_base_address_fields + - PRMRR_PHYBASE.PRMRR_MEMTYPE + - PRMRR_MASK.PRMRR_mask_bits + - PRMRR_MASK.PRMRR_VLD + - PRMRR_MASK.PRMRR_LOCK + - PRMRR_UNCORE_PHYBASE.PRMRR_base_address_fields + - PRMRR_UNCORE_MASK.PRMRR_mask_bits + - PRMRR_UNCORE_MASK.PRMRR_VLD + - PRMRR_UNCORE_MASK.PRMRR_LOCK + - BIOS_SE_SVN.PFAT_SE_SVN + - BIOS_SE_SVN.ANC_SE_SVN + - BIOS_SE_SVN.SCLEAN_SE_SVN + - BIOS_SE_SVN.SINIT_SE_SVN + - BIOS_SE_SVN_STATUS.LOCK + - SGX_DEBUG_MODE.SGX_DEBUG_MODE_STATUS_BIT + +.. note:: + - Will not run within the EFI Shell + """ _MODULE_NAME = 'sgx_check' from chipsec.module_common import BaseModule, ModuleResult, MTAG_HWCONFIG -from chipsec.defines import BIT0, BIT1, BIT2, BIT5, BIT6, BIT7, BIT8 +from chipsec.defines import BIT0, BIT1, BIT2, BIT5, BIT6, BIT7, BIT8 TAGS = [MTAG_HWCONFIG] @@ -40,23 +75,25 @@ class sgx_check(BaseModule): def is_supported(self): sgx_cpu_support = False - for tid in range(self.cs.msr.get_cpu_thread_count()): - status = self.helper.set_affinity(tid) - if status == -1: - if self.logger.VERBOSE: - self.logger.log("[*] Failed to set affinity to CPU{:d}".format(tid)) - (_, r_ebx, _, _) = self.cs.cpu.cpuid(0x07, 0x00) - if (r_ebx & BIT2): - if self.logger.VERBOSE: self.logger.log("[*] CPU{:d}: does support SGX".format(tid)) - sgx_cpu_support = True - else: - if self.logger.VERBOSE: self.logger.log("[*]CPU{:d}: does not support SGX".format(tid)) + if self.cs.helper.is_efi(): + self.logger.log_important('Currently this module cannot run within the EFI Shell. Exiting.') + else: + for tid in range(self.cs.msr.get_cpu_thread_count()): + status = self.helper.set_affinity(tid) + if status == -1: + self.logger.verbose_log("[*] Failed to set affinity to CPU{:d}".format(tid)) + (_, r_ebx, _, _) = self.cs.cpu.cpuid(0x07, 0x00) + if (r_ebx & BIT2): + self.logger.verbose_log("[*] CPU{:d}: does support SGX".format(tid)) + sgx_cpu_support = True + else: + self.logger.verbose_log("[*]CPU{:d}: does not support SGX".format(tid)) + self.logger.log_important('SGX not supported. Skipping module.') if not sgx_cpu_support: self.res = ModuleResult.NOTAPPLICABLE return sgx_cpu_support def check_sgx_config(self): - self.logger.start_test("Check SGX feature support") self.logger.log("[*] Test if CPU has support for SGX") sgx_ok = False @@ -69,20 +106,20 @@ class sgx_check(BaseModule): if bios_feature_control_enable: self.logger.log_good("Intel SGX is Enabled in BIOS") else: - self.logger.log_warning( "Intel SGX is not enabled in BIOS" ) + self.logger.log_important("Intel SGX is not enabled in BIOS") self.res = ModuleResult.WARNING self.logger.log("\n[*] Verifying IA32_FEATURE_CONTROL MSR is locked") locked = True for tid in range(self.cs.msr.get_cpu_thread_count()): feature_cntl_lock = self.cs.get_control('Ia32FeatureControlLock', tid) - if self.logger.VERBOSE: self.logger.log("[*] cpu{:d}: IA32_Feature_Control Lock = {:d}".format(tid, feature_cntl_lock)) + self.logger.verbose_log("[*] cpu{:d}: IA32_Feature_Control Lock = {:d}".format(tid, feature_cntl_lock)) if 0 == feature_cntl_lock: locked = False if locked: self.logger.log_good("IA32_Feature_Control locked") else: - self.logger.log_failed("IA32_Feature_Control is unlocked") + self.logger.log_bad("IA32_Feature_Control is unlocked") self.res = ModuleResult.FAILED # Verify that Protected Memory Range (PRM) is supported, MSR IA32_MTRRCAP (FEh) [12]=1 @@ -92,14 +129,14 @@ class sgx_check(BaseModule): for tid in range(self.cs.msr.get_cpu_thread_count()): mtrrcap = self.cs.read_register_field('MTRRCAP', 'PRMRR', False, tid) if (0 == mtrrcap): - if self.logger.VERBOSE: self.logger.log("[*] CPU{:d} Protected Memory Range configuration is not supported".format(tid)) + self.logger.verbose_log("[*] CPU{:d} Protected Memory Range configuration is not supported".format(tid)) else: prmrr_enable = True - if self.logger.VERBOSE: self.logger.log("[*] CPU{:d} Protected Memory Range configuration is supported".format(tid)) + self.logger.verbose_log("[*] CPU{:d} Protected Memory Range configuration is supported".format(tid)) if prmrr_enable: - self.logger.log_good( "Protected Memory Range configuration is supported" ) + self.logger.log_good("Protected Memory Range configuration is supported") else: - self.logger.log_failed( "Protected Memory Range configuration is not supported" ) + self.logger.log_bad("Protected Memory Range configuration is not supported") self.res - ModuleResult.FAILED # Check PRMRR configurations on each core. @@ -171,10 +208,10 @@ class sgx_check(BaseModule): (prmrr_base_memtype != prmrr_base_memtype_new)): prmrr_uniform = False if not prmrr_uniform: - self.logger.log_failed( "PRMRR config is not uniform across all CPUs" ) + self.logger.log_bad("PRMRR config is not uniform across all CPUs") self.res = ModuleResult.FAILED else: - self.logger.log_good( "PRMRR config is uniform across all CPUs" ) + self.logger.log_good("PRMRR config is uniform across all CPUs") prmrr_configs = [] # NB: BWG Provides only a list of 4 possible values, see item 5, section 2.1. So values e.g. 0x050 are prhibited, report error. config_support = False @@ -211,24 +248,24 @@ class sgx_check(BaseModule): self.logger.log("[*] Verifying PRMR memory type is valid") self.logger.log("[*] PRMRR memory type : 0x{:X}".format(prmrr_base_memtype)) if prmrr_base_memtype == 0x6: - self.logger.log_good( "PRMRR memory type is WB as expected" ) + self.logger.log_good("PRMRR memory type is WB as expected") else: - self.logger.log_failed( "Unexpected PRMRR memory type (not WB)" ) + self.logger.log_bad("Unexpected PRMRR memory type (not WB)") self.res = ModuleResult.FAILED self.logger.log("[*] PRMRR mask address: 0x{:012X}".format(prmrr_mask)) self.logger.log("[*] Verifying PRMR address are valid") self.logger.log("[*] PRMRR uncore mask valid: 0x{:d}".format(prmrr_uncore_mask_vld)) if prmrr_mask_vld == 0x1: - self.logger.log_good( "Mcheck marked PRMRR address as valid" ) + self.logger.log_good("Mcheck marked PRMRR address as valid") else: - self.logger.log_failed( "Mcheck marked PRMRR address as invalid" ) + self.logger.log_bad("Mcheck marked PRMRR address as invalid") self.res = ModuleResult.FAILED self.logger.log("[*] Verifying if PRMR mask register is locked") self.logger.log("[*] PRMRR mask lock: 0x{:X}".format(prmrr_mask_lock)) if prmrr_locked: - self.logger.log_good( "PRMRR MASK register is locked" ) + self.logger.log_good("PRMRR MASK register is locked") else: - self.logger.log_failed( "PRMRR MASK register is not locked" ) + self.logger.log_bad("PRMRR MASK register is not locked") self.res = ModuleResult.FAILED if check_uncore_vals: self.logger.log("[*] PRMRR uncore base address: 0x{:012X}".format(prmrr_uncore_base)) @@ -236,16 +273,16 @@ class sgx_check(BaseModule): self.logger.log("[*] Verifying PRMR uncore address are valid") self.logger.log("[*] PRMRR uncore mask valid: 0x{:X}".format(prmrr_uncore_mask_vld)) if prmrr_uncore_mask_vld == 0x1: - self.logger.log_good( "Mcheck marked uncore PRMRR address as valid" ) + self.logger.log_good("Mcheck marked uncore PRMRR address as valid") else: - self.logger.log_failed( "Mcheck marked uncore PRMRR address as invalid" ) + self.logger.log_bad("Mcheck marked uncore PRMRR address as invalid") self.res = ModuleResult.FAILED self.logger.log("[*] Verifying if PRMR uncore mask register is locked") self.logger.log("[*] PRMRR uncore mask lock: 0x{:X}".format(prmrr_uncore_mask_lock)) if prmrr_uncore_mask_lock == 0x1: - self.logger.log_good( "PMRR uncore MASK register is locked" ) + self.logger.log_good("PMRR uncore MASK register is locked") else: - self.logger.log_failed( "PMRR uncore MASK register is not locked" ) + self.logger.log_bad("PMRR uncore MASK register is not locked") self.res = ModuleResult.FAILED if bios_feature_control_enable and locked: @@ -255,23 +292,23 @@ class sgx_check(BaseModule): for tid in range(self.cs.msr.get_cpu_thread_count()): status = self.helper.set_affinity(tid) if status == -1: - if self.logger.VERBOSE: self.logger.log("[*] Failed to set affinity to CPU{:d}".format(tid)) + self.logger.verbose_log("[*] Failed to set affinity to CPU{:d}".format(tid)) (r_eax, r_ebx, r_ecx, r_edx) = self.cs.cpu.cpuid(0x012, 0x00) if (r_eax & BIT0): - if self.logger.VERBOSE: self.logger.log("[*] CPU{:d} SGX-1 instructions are supported".format(tid)) + self.logger.verbose_log("[*] CPU{:d} SGX-1 instructions are supported".format(tid)) sgx1_instr_support = True else: - if self.logger.VERBOSE: self.logger.log("[*] CPU{:d} SGX-1 instructions are not supported".format(tid)) + self.logger.verbose_log("[*] CPU{:d} SGX-1 instructions are not supported".format(tid)) if (r_eax & BIT1): - if self.logger.VERBOSE: self.logger.log("[*] CPU{:d} SGX-2 instructions are supported".format(tid)) + self.logger.verbose_log("[*] CPU{:d} SGX-2 instructions are supported".format(tid)) sgx2_instr_support = True else: - if self.logger.VERBOSE: self.logger.log("[*] CPU{:d} SGX-2 instructions are not supported".format(tid)) + self.logger.verbose_log("[*] CPU{:d} SGX-2 instructions are not supported".format(tid)) if sgx1_instr_support: self.logger.log_good("Intel SGX instructions are supported and available to use") sgx_ok = True else: - self.logger.log_failed("Intel SGX instructions are not supported on system") + self.logger.log_bad("Intel SGX instructions are not supported on system") sgx_ok = False if sgx2_instr_support: self.logger.log("[*] SGX-2 instructions are supported") @@ -284,11 +321,11 @@ class sgx_check(BaseModule): if sgx_ok and prmrr_enable and prmrr_uniform: self.logger.log_good("Intel SGX is available to use") elif (not sgx_ok) and (not bios_feature_control_enable) and prmrr_enable and prmrr_uniform: - self.logger.log_warning("Intel SGX instructions disabled by firmware") + self.logger.log_important("Intel SGX instructions disabled by firmware") if self.res == ModuleResult.PASSED: self.res = ModuleResult.WARNING else: - self.logger.log_failed("Intel SGX is not available to use") + self.logger.log_bad("Intel SGX is not available to use") self.res = ModuleResult.FAILED if self.cs.is_register_defined('BIOS_SE_SVN') and self.cs.is_register_defined('BIOS_SE_SVN_STATUS'): @@ -312,40 +349,34 @@ class sgx_check(BaseModule): self.logger.log("[*] Lock : {:d}".format(debug_lock)) if (1 == sgx_debug_status): - self.logger.log_failed("SGX debug mode is enabled") + self.logger.log_bad("SGX debug mode is enabled") self.res = ModuleResult.FAILED else: self.logger.log_good("SGX debug mode is disabled") if (0 == debug_enable): self.logger.log_good("Silicon debug features are disabled") else: - self.logger.log_failed("Silicon debug features are not disabled") + self.logger.log_bad("Silicon debug features are not disabled") self.res = ModuleResult.FAILED if (0 == debug_enable) and (1==sgx_debug_status): - self.logger.log_failed("Enabling sgx_debug without enabling debug mode in msr IA32_DEBUG_INTERFACE is not a valid configuration") + self.logger.log_bad("Enabling sgx_debug without enabling debug mode in msr IA32_DEBUG_INTERFACE is not a valid configuration") self.res = ModuleResult.FAILED if (1 == debug_lock): self.logger.log_good("Silicon debug Feature Control register is locked") else: - self.logger.log_failed("Silicon debug Feature Control register is not locked") + self.logger.log_bad("Silicon debug Feature Control register is not locked") self.res = ModuleResult.FAILED return self.res def run(self, module_argv): - if self.cs.helper.is_efi(): - self.logger.error( 'Currently this module cannot run within the EFI Shell. Exiting.' ) - return ModuleResult.SKIPPED + self.logger.start_test("Check SGX feature support") + + self.res = self.check_sgx_config() + if self.res == ModuleResult.PASSED: + self.logger.log_passed('All SGX checks passed') + elif self.res == ModuleResult.WARNING: + self.logger.log_warning('One or more SGX checks detected a warning') else: - self.res = self.check_sgx_config() - if self.res == ModuleResult.PASSED: - self.logger.log_passed_check('All SGX checks passed') - elif self.res == ModuleResult.WARNING: - self.logger.log_warn_check('One or more SGX checks detected a warning') - elif self.res == ModuleResult.SKIPPED: - self.logger.log_skipped_check('SGX test is being skipped') - elif self.res == ModuleResult.NOTAPPLICABLE: - self.logger.log_not_applicable_check('SGX test is being skipped') - else: - self.logger.log_failed_check('One or more SGX checks failed') - return self.res + self.logger.log_failed('One or more SGX checks failed') + return self.res