hackedteam/vector-edk

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

Summary

Maintainability
B
4 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/secureboot/keys.py__ - verify protections of Secure Boot key EFI variables


from chipsec.module_common import *

from chipsec.file          import *
from chipsec.hal.uefi      import *

# ############################################################
# SPECIFY PLATFORMS THIS MODULE IS APPLICABLE TO
# ############################################################
_MODULE_NAME = 'keys'
cs.add_available_module(_MODULE_NAME, 'COMMON')

TAGS = [MTAG_SECUREBOOT]

class keys(BaseModule):
    SECURE = 0x1
    INSECURE = 0x2
    ERROR = 0x4
    
    def __init__(self):
        BaseModule.__init__(self)
        self._uefi  = UEFI( self.cs.helper )
    
            
    
    def check_EFI_variable_authentication( self, name, guid ):
        self.logger.log( "[*] Checking EFI variable %s {%s}.." % (name, guid) )
        orig_var = self._uefi.get_EFI_variable( name, guid, None )
        if not orig_var:
            self.logger.log( "[*] EFI variable %s {%s} doesn't exist" % (name, guid) )
            return keys.ERROR
        fname = name + '_' + guid + '.bin'
        if self.logger.VERBOSE: write_file( fname, orig_var )
        origvar_len = len(orig_var)
        mod_var = chr( ord(orig_var[0]) ^ 0xFF ) + orig_var[1:] 
        if origvar_len > 1: mod_var = mod_var[:origvar_len-1] + chr( ord(mod_var[origvar_len-1]) ^ 0xFF )
        if self.logger.VERBOSE: write_file( fname + '.mod', mod_var )
        status = self._uefi.set_EFI_variable( name, guid, mod_var )
        if not status: self.logger.log( '[*] Writing EFI variable %s did not succeed. Verifying contents..' % name )
        new_var = self._uefi.get_EFI_variable( name, guid, None )
        if self.logger.VERBOSE: write_file( fname + '.new', new_var )
        ok = (origvar_len == len(new_var))
        for i in range( origvar_len ):
            if not (new_var[i] == orig_var[i]):
                ok = keys.INSECURE
                break
        if ok == keys.INSECURE:
            self.logger.log_bad( "EFI variable %s is not protected! It has been modified. Restoring original contents.." % name )
            self._uefi.set_EFI_variable( name, guid, orig_var )
        else:                                                                     
            self.logger.log_good( "Could not modify EFI variable %s {%s}" % (name, guid) )
        return ok
    
    # checks authentication of Secure Boot EFI variables
    def check_secureboot_key_variables(self):
        sts = 0
        sts |= self.check_EFI_variable_authentication( EFI_VAR_NAME_PK,         EFI_VARIABLE_DICT[EFI_VAR_NAME_PK]         )
        sts |= self.check_EFI_variable_authentication( EFI_VAR_NAME_KEK,        EFI_VARIABLE_DICT[EFI_VAR_NAME_KEK]        )
        sts |= self.check_EFI_variable_authentication( EFI_VAR_NAME_db,         EFI_VARIABLE_DICT[EFI_VAR_NAME_db]         )
        sts |= self.check_EFI_variable_authentication( EFI_VAR_NAME_dbx,        EFI_VARIABLE_DICT[EFI_VAR_NAME_dbx]        )
        sts |= self.check_EFI_variable_authentication( EFI_VAR_NAME_SecureBoot, EFI_VARIABLE_DICT[EFI_VAR_NAME_SecureBoot] )
        sts |= self.check_EFI_variable_authentication( EFI_VAR_NAME_SetupMode,  EFI_VARIABLE_DICT[EFI_VAR_NAME_SetupMode]  )
        #sts |= self.check_EFI_variable_authentication( EFI_VAR_NAME_CustomMode, EFI_VARIABLE_DICT[EFI_VAR_NAME_CustomMode] )
        if (sts & keys.ERROR) != 0: self.logger.log_important( "Some Secure Boot variables don't exist" )
    
        ok = ((sts & keys.INSECURE) == 0)
        self.logger.log('')
        if ok: self.logger.log_passed_check( 'All existing Secure Boot EFI variables seem to be protected' )
        else:  self.logger.log_failed_check( 'One or more Secure Boot variables are not protected' )
        return ok
    
    
    # --------------------------------------------------------------------------
    # run( module_argv )
    # Required function: run here all tests from this module
    # --------------------------------------------------------------------------
    def run( self, module_argv ):
        #self.logger.VERBOSE = True
        self.logger.start_test( "Protection of Secure Boot Key and Configuraion EFI Variables" )
        if not (self.cs.helper.is_win8_or_greater() or self.cs.helper.is_linux()):
            self.logger.log_skipped_check( 'Currently this module can only run on Windows 8 or greater or Linux. Exiting..' )
            return ModuleResult.SKIPPED
        return self.check_secureboot_key_variables()