Example #1
0
class bios_wp(BaseModule):

    def __init__(self):
        BaseModule.__init__(self)
        self.spi    = SPI( self.cs )

    def is_supported(self):
        return True

    def check_BIOS_write_protection(self):
        self.logger.start_test( "BIOS Region Write Protection" )
        #
        # BIOS Control Register
        #
        #reg_value = chipsec.chipset.read_register(self.cs, 'BC')
        #chipsec.chipset.print_register(self.cs, 'BC', reg_value)

        #ble    = chipsec.chipset.get_register_field(self.cs, 'BC', reg_value, 'BLE')
        ble = self.cs.get_control('BiosLockEnable', with_print=True)
        #bioswe = self.cs.get_register_field('BC', reg_value, 'BIOSWE')
        bioswe = self.cs.get_control('BiosWriteEnable')
        #smmbwp = chipsec.chipset.get_register_field(self.cs, 'BC', reg_value, 'SMM_BWP')
        smmbwp = self.cs.get_control( 'SmmBiosWriteProtection' )

        # Is the BIOS flash region write protected?
        write_protected = 0
        if 1 == ble and 0 == bioswe:
            if 1 == smmbwp:
                self.logger.log_good( "BIOS region write protection is enabled (writes restricted to SMM)" )
                write_protected = 1
            else:
                self.logger.log_important( "Enhanced SMM BIOS region write protection has not been enabled (SMM_BWP is not used)" )
        else:
            self.logger.log_bad( "BIOS region write protection is disabled!" )

        return write_protected == 1

    def check_SPI_protected_ranges(self):
        (bios_base,bios_limit,bios_freg) = self.spi.get_SPI_region( BIOS )
        self.logger.log( "\n[*] BIOS Region: Base = 0x{:08X}, Limit = 0x{:08X}".format(bios_base,bios_limit) )
        self.spi.display_SPI_Protected_Ranges()

        pr_cover_bios = False
        pr_partial_cover_bios = False
    #    for j in range(5):
    #        (base,limit,wpe,rpe,pr_reg_off,pr_reg_value) = spi.get_SPI_Protected_Range( j )
    #        if (wpe == 1 and base < limit and base <= bios_base and limit >= bios_limit):
    #            pr_cover_bios = True
    #        if (wpe == 1 and base < limit and limit > bios_base):
    #            pr_partial_cover_bios = True

        areas_to_protect  = [(bios_base, bios_limit)]
        protected_areas = list()


        for j in range(5):
            (base,limit,wpe,rpe,pr_reg_off,pr_reg_value) = self.spi.get_SPI_Protected_Range( j )
            if base > limit: continue
            if wpe == 1:
                for area in areas_to_protect:
                    # overlap bottom
                    start,end = area
                    if base <= start and limit >= start:
                        if limit >= end:
                            areas_to_protect.remove(area)
                        else:
                            areas_to_protect.remove(area)
                            area = (limit+1,end)
                            areas_to_protect.append(area)

                    # overlap top
                    elif base <= end and limit >= end:
                        if base <= start:
                            areas_to_protect.remove(area)
                        else:
                            areas_to_protect.remove(area)
                            area = (start,base-1)
                            areas_to_protect.append(area)
                            start,end = area
                    # split
                    elif base > start and limit < end:
                        areas_to_protect.remove(area)
                        areas_to_protect.append((start,base-1))
                        areas_to_protect.append((limit+1, end))


        if (len(areas_to_protect)  == 0):
            pr_cover_bios = True
        else:
            if (len(areas_to_protect) != 1 or areas_to_protect[0] != (bios_base,bios_limit)):
                pr_partial_cover_bios = True

        if pr_partial_cover_bios:
            self.logger.log( '' )
            self.logger.log_important( "SPI protected ranges write-protect parts of BIOS region (other parts of BIOS can be modified)" )

        else:
            if not pr_cover_bios:
                self.logger.log( '' )
                self.logger.log_important( "None of the SPI protected ranges write-protect BIOS region" )

        return pr_cover_bios

    # --------------------------------------------------------------------------
    # run( module_argv )
    # Required function: run here all tests from this module
    # --------------------------------------------------------------------------
    def run(self, module_argv ):
        wp = self.check_BIOS_write_protection()
        spr = self.check_SPI_protected_ranges()

        self.logger.log('')
        if wp:
            if spr:  self.logger.log_passed_check( "BIOS is write protected (by SMM and SPI Protected Ranges)" )
            else:    self.logger.log_passed_check( "BIOS is write protected" )
        else:
            if spr:  self.logger.log_passed_check( "SPI Protected Ranges are configured to write protect BIOS" )
            else:
                self.logger.log_important( 'BIOS should enable all available SMM based write protection mechanisms or configure SPI protected ranges to protect the entire BIOS region' )
                self.logger.log_failed_check( "BIOS is NOT protected completely" )

        if wp or spr: return ModuleResult.PASSED
        else: return ModuleResult.FAILED
Example #2
0
class bios_wp(BaseModule):
    def __init__(self):
        BaseModule.__init__(self)
        self.spi = SPI(self.cs)

    def is_supported(self):
        return True

    def check_BIOS_write_protection(self):
        ble = self.cs.get_control('BiosLockEnable', with_print=True)
        bioswe = self.cs.get_control('BiosWriteEnable')
        smmbwp = self.cs.get_control('SmmBiosWriteProtection')

        # Is the BIOS flash region write protected?
        write_protected = 0
        if (1 == ble) and (0 == bioswe):
            if 1 == smmbwp:
                self.logger.log_good(
                    "BIOS region write protection is enabled (writes restricted to SMM)"
                )
                write_protected = 1
            else:
                self.logger.log_important(
                    "Enhanced SMM BIOS region write protection has not been enabled (SMM_BWP is not used)"
                )
        else:
            self.logger.log_bad("BIOS region write protection is disabled!")

        return write_protected == 1

    def check_SPI_protected_ranges(self):
        (bios_base, bios_limit, _) = self.spi.get_SPI_region(BIOS)
        self.logger.log(
            "\n[*] BIOS Region: Base = 0x{:08X}, Limit = 0x{:08X}".format(
                bios_base, bios_limit))
        self.spi.display_SPI_Protected_Ranges()

        pr_cover_bios = False
        pr_partial_cover_bios = False

        areas_to_protect = [(bios_base, bios_limit)]

        for j in range(5):
            (base, limit, wpe, _, _, _) = self.spi.get_SPI_Protected_Range(j)
            if base > limit:
                continue
            if wpe == 1:
                areas = areas_to_protect[:]
                for area in areas:
                    (start, end) = area
                    if (base <= start) and (limit >= start):  # overlap bottom
                        if limit >= end:
                            areas_to_protect.remove(area)
                        else:
                            areas_to_protect.remove(area)
                            area = (limit + 1, end)
                            areas_to_protect.append(area)
                    elif (base <= end) and (limit >= end):  # overlap top
                        if base <= start:
                            areas_to_protect.remove(area)
                        else:
                            areas_to_protect.remove(area)
                            area = (start, base - 1)
                            areas_to_protect.append(area)
                    elif (base > start) and (limit < end):  # split
                        areas_to_protect.remove(area)
                        areas_to_protect.append((start, base - 1))
                        areas_to_protect.append((limit + 1, end))

        if (len(areas_to_protect) == 0):
            pr_cover_bios = True
        else:
            if (len(areas_to_protect) != 1) or (areas_to_protect[0] !=
                                                (bios_base, bios_limit)):
                pr_partial_cover_bios = True

        if pr_partial_cover_bios:
            self.logger.log('')
            self.logger.log_important(
                "SPI protected ranges write-protect parts of BIOS region (other parts of BIOS can be modified)"
            )
        else:
            if not pr_cover_bios:
                self.logger.log('')
                self.logger.log_important(
                    "None of the SPI protected ranges write-protect BIOS region"
                )

        return pr_cover_bios

    # --------------------------------------------------------------------------
    # run( module_argv )
    # Required function: run here all tests from this module
    # --------------------------------------------------------------------------
    def run(self, module_argv):
        self.logger.start_test("BIOS Region Write Protection")
        wp = self.check_BIOS_write_protection()
        spr = self.check_SPI_protected_ranges()

        self.logger.log('')
        if wp:
            if spr:
                self.logger.log_passed(
                    "BIOS is write protected (by SMM and SPI Protected Ranges)"
                )
            else:
                self.logger.log_passed("BIOS is write protected")
        else:
            if spr:
                self.logger.log_passed(
                    "SPI Protected Ranges are configured to write protect BIOS"
                )
            else:
                self.logger.log_important(
                    'BIOS should enable all available SMM based write protection mechanisms.'
                )
                self.logger.log_important(
                    'Or configure SPI protected ranges to protect the entire BIOS region.'
                )
                self.logger.log_failed("BIOS is NOT protected completely")

        if wp or spr:
            self.res = ModuleResult.PASSED
        else:
            self.res = ModuleResult.FAILED

        return self.res