/** Some Secure Boot Policy Variable may update following other variable changes(SecureBoot follows PK change, etc). Record their initial State when variable write service is ready. **/ VOID EFIAPI RecordSecureBootPolicyVarData( VOID ) { EFI_STATUS Status; // // Record initial "SecureBoot" variable value. // It is used to detect SecureBoot variable change in SecureBootHook. // Status = InternalGetVariable ( EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID **)&mSecureBootVarData, &mSecureBootVarDataSize ); if (EFI_ERROR(Status)) { // // Read could fail when Auth Variable solution is not supported // DEBUG((DEBUG_INFO, "RecordSecureBootPolicyVarData GetVariable %s Status %x\n", EFI_SECURE_BOOT_MODE_NAME, Status)); } }
/** This service is a checker handler for the UEFI Runtime Service SetVariable() @param VariableName the name of the vendor's variable, as a Null-Terminated Unicode String @param VendorGuid Unify identifier for vendor. @param Attributes Point to memory location to return the attributes of variable. If the point is NULL, the parameter would be ignored. @param DataSize The size in bytes of Data-Buffer. @param Data Point to the content of the variable. @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as defined by the Attributes. @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied, or the DataSize exceeds the maximum allowed. @retval EFI_INVALID_PARAMETER VariableName is an empty Unicode string. @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved due to a hardware failure. @retval EFI_WRITE_PROTECTED The variable in question is read-only. @retval EFI_WRITE_PROTECTED The variable in question cannot be deleted. @retval EFI_SECURITY_VIOLATION The variable could not be written due to EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set but the AuthInfo does NOT pass the validation check carried out by the firmware. @retval EFI_NOT_FOUND The variable trying to be updated or deleted was not found. **/ EFI_STATUS EFIAPI SetVariableCheckHandlerMor ( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data ) { UINTN MorLockDataSize; BOOLEAN MorLock; EFI_STATUS Status; // // do not handle non-MOR variable // if (!IsAnyMorVariable (VariableName, VendorGuid)) { return EFI_SUCCESS; } MorLockDataSize = sizeof(MorLock); Status = InternalGetVariable ( MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, &gEfiMemoryOverwriteRequestControlLockGuid, NULL, &MorLockDataSize, &MorLock ); if (!EFI_ERROR (Status) && MorLock) { // // If lock, deny access // return EFI_INVALID_PARAMETER; } // // Delete not OK // if ((DataSize != sizeof(UINT8)) || (Data == NULL) || (Attributes == 0)) { return EFI_INVALID_PARAMETER; } // // check format // if (IsMorLockVariable(VariableName, VendorGuid)) { // // set to any other value not OK // if ((*(UINT8 *)Data != 1) && (*(UINT8 *)Data != 0)) { return EFI_INVALID_PARAMETER; } } // // Or grant access // return EFI_SUCCESS; }
/** SecureBoot Hook for SetVariable. @param[in] VariableName Name of Variable to be found. @param[in] VendorGuid Variable vendor GUID. **/ VOID EFIAPI SecureBootHook ( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid ) { EFI_STATUS Status; UINTN VariableDataSize; VOID *VariableData; if (!IsSecureBootPolicyVariable (VariableName, VendorGuid)) { return ; } // // We should NOT use Data and DataSize here,because it may include signature, // or is just partial with append attributes, or is deleted. // We should GetVariable again, to get full variable content. // Status = InternalGetVariable ( VariableName, VendorGuid, &VariableData, &VariableDataSize ); if (EFI_ERROR (Status)) { VariableData = NULL; VariableDataSize = 0; } Status = MeasureVariable ( VariableName, VendorGuid, VariableData, VariableDataSize ); DEBUG ((EFI_D_ERROR, "MeasureBootPolicyVariable - %r\n", Status)); if (VariableData != NULL) { FreePool (VariableData); } return ; }
/** SecureBoot Hook for SetVariable. @param[in] VariableName Name of Variable to be found. @param[in] VendorGuid Variable vendor GUID. **/ VOID EFIAPI SecureBootHook ( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid ) { EFI_STATUS Status; UINTN VariableDataSize; VOID *VariableData; if (!IsSecureBootPolicyVariable (VariableName, VendorGuid)) { return ; } // // We should NOT use Data and DataSize here,because it may include signature, // or is just partial with append attributes, or is deleted. // We should GetVariable again, to get full variable content. // Status = InternalGetVariable ( VariableName, VendorGuid, &VariableData, &VariableDataSize ); if (EFI_ERROR (Status)) { // // Measure DBT only if present and not empty // if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0 && CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid)) { DEBUG((DEBUG_INFO, "Skip measuring variable %s since it's deleted\n", EFI_IMAGE_SECURITY_DATABASE2)); return; } else { VariableData = NULL; VariableDataSize = 0; } } Status = MeasureVariable ( VariableName, VendorGuid, VariableData, VariableDataSize ); DEBUG ((EFI_D_INFO, "MeasureBootPolicyVariable - %r\n", Status)); if (VariableData != NULL) { FreePool (VariableData); } // // "SecureBoot" is 8bit & read-only. It can only be changed according to PK update // if ((StrCmp (VariableName, EFI_PLATFORM_KEY_NAME) == 0) && CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)) { Status = InternalGetVariable ( EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, &VariableData, &VariableDataSize ); if (EFI_ERROR (Status)) { return; } // // If PK update is successful. "SecureBoot" shall always exist ever since variable write service is ready // ASSERT(mSecureBootVarData != NULL); if (CompareMem(mSecureBootVarData, VariableData, VariableDataSize) != 0) { FreePool(mSecureBootVarData); mSecureBootVarData = VariableData; mSecureBootVarDataSize = VariableDataSize; DEBUG((DEBUG_INFO, "%s variable updated according to PK change. Remeasure the value!\n", EFI_SECURE_BOOT_MODE_NAME)); Status = MeasureVariable ( EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, mSecureBootVarData, mSecureBootVarDataSize ); DEBUG ((DEBUG_INFO, "MeasureBootPolicyVariable - %r\n", Status)); } else { // // "SecureBoot" variable is not changed // FreePool(VariableData); } } return ; }