mirror of
https://github.com/chipsec/chipsec
synced 2026-06-08 13:31:00 +00:00
Add usage documentation to sgx_check.py
This commit is contained in:
committed by
Nathaniel Mitchell
parent
28a5234170
commit
f4f196b47f
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user