/** @file ;****************************************************************************** ;* Copyright (c) 2018 - 2021, Insyde Software Corp. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ #include "ImageCheck.h" #include "IhisiSmm.h" AUTHENTICATION_CHECK_FUNCTION mImageCheckTableBootGuard[] = { ImageCheckBootGuardCheckLegacyBoot, ImageCheckBootGuardRequestFITP, ImageCheckBootGuardRequestFIT, ImageCheckBootGuardValidateFIT, ImageCheckBootGuardCollectFITInfo, ImageCheckBootGuardRequestBPM, ImageCheckBootGuardValidateBPM, ImageCheckBootGuardCheckBPSVN, ImageCheckBootGuardRequestACM, ImageCheckBootGuardCheckACMSVN, ImageCheckBootGuardFindKM, ImageCheckBootGuardCheckKMSVN, NULL }; AUTHENTICATION_CHECK_FUNCTION mImageCheckTableNullTable[] = { NULL }; AUTHENTICATION_CHECK_TABLE mImageCheckTable[] = { { FBTS_IMAGE_CHECK_FAILURE_CODE_BOOT_GUARD, mImageCheckTableBootGuard }, { FBTS_IMAGE_CHECK_FAILURE_CODE_NONE, mImageCheckTableNullTable } }; STATIC UINTN mImageCheckTableIndex = 0; STATIC UINTN mImageCheckFunctionIndex = 0; STATIC UINTN mRequestedLength = 0; STATIC UINTN mFITPointer = 0; STATIC LOCATION_INFO mLocationInfoBPM = { 0 }; STATIC LOCATION_INFO mLocationInfoACM = { 0 }; STATIC LOCATION_INFO_LIST *mLocationInfoListKM = NULL; STATIC LOCATION_INFO_LIST *mCurrentLocationInfoListKM = NULL; /** IHISI Function 4Dh. Arguments : None Returns : EFI_SUCCESS - Image is valid so far EFI_UNSUPPORTED - Image is valid and the last check is bypassed EFI_BAD_BUFFER_SIZE - Invalid data size Other - Image is invalid @param None **/ EFI_STATUS ImageCheck ( VOID ) { EFI_STATUS Status; IHISI_STATUS_CODE ReturnStatus; UINTN Address; UINTN Length; BOOLEAN FurtherDataRequired; BOOLEAN Repeat; UINTN ErrorIndication; BOOLEAN IsValid; Status = EFI_SUCCESS; Address = (UINTN) mH2OIhisi->ReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI); Length = (UINTN) mH2OIhisi->ReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); FurtherDataRequired = FALSE; Repeat = FALSE; ErrorIndication = 0; // // If the Length is zero, it means input block size is by query action. // if (Length == 0) { IsValid = mH2OIhisi->BufferInCmdBuffer ((VOID *) Address, FBTS_IMAGE_CHECK_IMAGE_SIZE_MAX); } else { IsValid = mH2OIhisi->BufferInCmdBuffer ((VOID *) Address, Length); } // ENCODE_IHISI_STATUS if (!IsValid) { mH2OIhisi->WriteCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RSI, FBTS_IMAGE_CHECK_FAILURE_CODE_BOOT_GUARD); return IHISI_FBTS_PERMISSION_DENIED; } // // Check if the first calling // if (Length == 0) { mImageCheckTableIndex = 0; mImageCheckFunctionIndex = 0; mRequestedLength = 0; // if (FixedPcdGetBool (PcdBootGuardEnable)) { mFITPointer = 0; mLocationInfoBPM.Address = 0; mLocationInfoBPM.Length = 0; mLocationInfoACM.Address = 0; mLocationInfoACM.Length = 0; ImageCheckFreeLocationInfoList (mLocationInfoListKM); mLocationInfoListKM = NULL; mCurrentLocationInfoListKM = NULL; // } } if ((Length < mRequestedLength) || (Length > FBTS_IMAGE_CHECK_IMAGE_SIZE_MAX)) { mH2OIhisi->WriteCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RSI, FBTS_IMAGE_CHECK_FAILURE_CODE_BOOT_GUARD); return IHISI_FBTS_PERMISSION_DENIED; } while (mImageCheckTableIndex < (sizeof (mImageCheckTable) / sizeof (AUTHENTICATION_CHECK_TABLE))) { Status = EFI_SUCCESS; FurtherDataRequired = FALSE; Repeat = FALSE; while ((!EFI_ERROR (Status)) && (!FurtherDataRequired) && (mImageCheckTable[mImageCheckTableIndex].Function[mImageCheckFunctionIndex] != NULL)) { Status = mImageCheckTable[mImageCheckTableIndex].Function[mImageCheckFunctionIndex] (&Address, &Length, &FurtherDataRequired, &Repeat); if (Length > FBTS_IMAGE_CHECK_IMAGE_SIZE_MAX) { Status = EFI_BAD_BUFFER_SIZE; } if (EFI_ERROR (Status)) { FurtherDataRequired = FALSE; break; } if (!Repeat) { mImageCheckFunctionIndex = mImageCheckFunctionIndex + 1; } } if (FurtherDataRequired) { break; } if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) { ErrorIndication = mImageCheckTable[mImageCheckTableIndex].TableCode; break; } mImageCheckTableIndex = mImageCheckTableIndex + 1; mImageCheckFunctionIndex = 0; } if (FurtherDataRequired) { mH2OIhisi->WriteCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RDI, (UINT32)Address); mH2OIhisi->WriteCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX, (UINT32)Length); mRequestedLength = mH2OIhisi->ReadCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RCX); } mH2OIhisi->WriteCpuReg32 (EFI_SMM_SAVE_STATE_REGISTER_RSI, (UINT32) ErrorIndication); ReturnStatus = FurtherDataRequired ? IHISI_FBTS_NEXT_BLOCK : ImageCheckStatusTranslation (Status); return ReturnStatus; } /** To free the location info buffers allocated. Arguments : LocationInfoList - Pointer of the list of the location info buffers Returns : EFI_SUCCESS - Process complete Other - Process can't be done @param [in, out] LocationInfoList Pointer of the list of the location info buffers **/ EFI_STATUS ImageCheckFreeLocationInfoList ( IN OUT LOCATION_INFO_LIST *LocationInfoList ) { EFI_STATUS Status; Status = EFI_SUCCESS; if (LocationInfoList == NULL) { return EFI_SUCCESS; } if (LocationInfoList->NextPtr != NULL) { Status = ImageCheckFreeLocationInfoList (LocationInfoList->NextPtr); } if (!EFI_ERROR (Status)) { Status = gSmst->SmmFreePool (LocationInfoList); } return Status; } /** To translate the EFI Status to the corresponding IHISI Status for the ImageCheck function. Arguments : Status - EFI Status Returns : IHISI Status @param [in] Status EFI Status @param [out] ReturnStatus IHISI_SUCCESS continue IHISI_END_FUNCTION_CHAIN Pass Ihisi 4Dh check IHISI_FBTS_PERMISSION_DENIED Ihisi 4Dh check fail **/ IHISI_STATUS_CODE ImageCheckStatusTranslation ( IN EFI_STATUS Status ) { IHISI_STATUS_CODE ReturnStatus; switch (Status) { case EFI_SUCCESS: case EFI_UNSUPPORTED: ReturnStatus = IHISI_SUCCESS; break; case EFI_END_OF_FILE: ReturnStatus = IHISI_END_FUNCTION_CHAIN; break; default: ReturnStatus = IHISI_FBTS_PERMISSION_DENIED; break; } return ReturnStatus; } /** To check if the Boot State of Boot Guard is Legacy Boot(Profile 0). Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - Not Legacy Boot EFI_UNSUPPORTED - Legacy Boot @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardCheckLegacyBoot ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { EFI_STATUS Status; REVOCATION_VALUE Revocation; UINTN Size; UINT32 MeStatus; *FurtherDataRequired = FALSE; *Repeat = FALSE; Status = BootGuardPlatformLibGetMeStatus (&MeStatus); if ((EFI_ERROR(Status))) { MeStatus = ME_NOT_READY; } if ((MeStatus & 0x0f) == ME_READY){ return (BootGuardPlatformLibDetermineBootState () == BootGuardBootStateLegacyBoot ) ? EFI_END_OF_FILE : EFI_SUCCESS; } else { Size = sizeof (Revocation); Status = RestoreLockBox (&gArbSvnInfoGuid, &Revocation, &Size); if (!EFI_ERROR (Status)) { return ((Revocation.BootGuardStatus) == BootGuardBootStateLegacyBoot) ? EFI_END_OF_FILE : EFI_SUCCESS; } } return EFI_DEVICE_ERROR; } /** To request FITP. Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - FITP requested @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardRequestFITP ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { *Address = ( UINTN )R_FITP; *Length = S_FITP; *FurtherDataRequired = TRUE; *Repeat = FALSE; return EFI_SUCCESS; } /** To request FIT. Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - FIT requested EFI_DEVICE_ERROR - FIT is unavailable @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardRequestFIT ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { EFI_STATUS Status; FIT_ENTRY *FIT; FIT = NULL; if (mFITPointer == 0) { mFITPointer = (UINTN)(*(UINT32 *)((UINTN)(*Address))); *Address = (UINTN)mFITPointer; *Length = (UINTN)(sizeof (FIT_ENTRY)); *FurtherDataRequired = TRUE; *Repeat = TRUE; return EFI_SUCCESS; } FIT = (FIT_ENTRY *)((UINTN)(*Address)); Status = FITPlatformLibValidateFITHeaderAddress (FIT); if (EFI_ERROR (Status)) { *FurtherDataRequired = FALSE; *Repeat = FALSE; return EFI_DEVICE_ERROR; } *Address = (UINTN)mFITPointer; *Length = (UINTN )(((FIT->Size[2] << 16) | (FIT->Size[1] << 8) | (FIT->Size[0] << 0)) * V_FIT_ENTRY_FIT_HEADER_SIZE_GRANULARITY); *FurtherDataRequired = TRUE; *Repeat = FALSE; return Status; } /** To validate FIT. Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - Valid EFI_DEVICE_ERROR - Invalid @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardValidateFIT ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { EFI_STATUS Status; FIT_ENTRY *FIT; FIT = (FIT_ENTRY *)((UINTN)(*Address)); Status = FITPlatformLibValidateFIT (FIT); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; } *FurtherDataRequired = FALSE; *Repeat = FALSE; return Status; } /** To collect information of the components in FIT. Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - Information collected EFI_BAD_BUFFER_SIZE - Error on allocating saving buffer @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardCollectFITInfo ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { EFI_STATUS Status; FIT_ENTRY *FIT; UINTN FITEntryMaxIndex; UINTN Index; LOCATION_INFO_LIST **LocationInfoListKM; UINT8 ElementsCheck; Status = EFI_SUCCESS; FIT = (FIT_ENTRY *)((UINTN)(*Address)); FITEntryMaxIndex = ((( FIT->Size[2] << 16) | (FIT->Size[1] << 8) | (FIT->Size[0] << 0)) * 0x10) / (sizeof (FIT_ENTRY)); Index = 0; LocationInfoListKM = &mLocationInfoListKM; ElementsCheck = 0; for (Index = 0; Index < FITEntryMaxIndex; Index = Index + 1) { if (FIT[Index].Type == V_FIT_ENTRY_TYPE_KEY_MANIFEST) { Status = gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (LOCATION_INFO_LIST), (VOID**)LocationInfoListKM); if (EFI_ERROR (Status) || *LocationInfoListKM == NULL) { Status = EFI_BAD_BUFFER_SIZE; ASSERT_EFI_ERROR (Status); break; } (*LocationInfoListKM)->LocationInfo.Address = (UINTN)FIT[Index].Address; (*LocationInfoListKM)->LocationInfo.Length = (UINTN)((FIT[Index].Size[2] << 16) | (FIT[Index].Size[1] << 8) | (FIT[Index].Size[0] << 0)); (*LocationInfoListKM)->NextPtr = NULL; LocationInfoListKM = &((*LocationInfoListKM )->NextPtr); ElementsCheck |= BIT0; } if (FIT[Index].Type == V_FIT_ENTRY_TYPE_BOOT_POLICY_MANIFEST) { mLocationInfoBPM.Address = (UINTN)FIT[Index].Address; mLocationInfoBPM.Length = (UINTN)((FIT[Index].Size[2] << 16) | (FIT[Index].Size[1] << 8) | (FIT[Index].Size[0] << 0)); ElementsCheck |= BIT1; } if (FIT[Index].Type == V_FIT_ENTRY_TYPE_STARTUP_AC_MODULE) { mLocationInfoACM.Address = (UINTN)FIT[Index].Address; mLocationInfoACM.Length = (UINTN)((FIT[Index].Size[2] << 16) | (FIT[Index].Size[1] << 8) | (FIT[Index].Size[0] << 0)); ElementsCheck |= BIT2; } } *FurtherDataRequired = FALSE; *Repeat = FALSE; if (ElementsCheck != 7) { //BIT0 | BIT1 | BIT2 *FurtherDataRequired = TRUE; Status = EFI_DEVICE_ERROR; } return Status; } /** To request BPM. Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - BPM requested EFI_NOT_FOUND - BPM is unavailable @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardRequestBPM ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { if ((mLocationInfoBPM.Address == 0) || (mLocationInfoBPM.Length == 0)) { return EFI_NOT_FOUND; } *Address = (UINTN)mLocationInfoBPM.Address; *Length = (UINTN)mLocationInfoBPM.Length; *FurtherDataRequired = TRUE; *Repeat = FALSE; return EFI_SUCCESS; } /** To validate BPM. Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - Valid EFI_DEVICE_ERROR - Invalid @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardValidateBPM ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { EFI_STATUS Status; BOOT_POLICY_MANIFEST_HEADER *BPMH; BPMH = (BOOT_POLICY_MANIFEST_HEADER *)((UINTN)(*Address)); Status = BootGuardPlatformLibValidateBPMStructureID (BPMH); if ( EFI_ERROR ( Status ) ) { Status = EFI_DEVICE_ERROR; } *FurtherDataRequired = FALSE; *Repeat = FALSE; return Status; } /** To check BPSVN. Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - BPSVN is valid EFI_SECURITY_VIOLATION - BPSVN is invalid EFI_UNSUPPORTED - Revocation values are unavailable @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardCheckBPSVN ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { EFI_STATUS Status; BOOT_POLICY_MANIFEST_HEADER *BPMH; REVOCATION_VALUE Revocation; UINTN Size; BPMH = (BOOT_POLICY_MANIFEST_HEADER *)((UINTN)(*Address)); // // Restore BPM SVN value from LockBox. // Size = sizeof (Revocation); Status = RestoreLockBox (&gArbSvnInfoGuid, &Revocation, &Size); if (EFI_ERROR (Status)) { Status = EFI_UNSUPPORTED; } else { if (BPMH->BpmRevocation < Revocation.BPMSVN) { Status = EFI_SECURITY_VIOLATION; } } *FurtherDataRequired = FALSE; *Repeat = FALSE; return Status; } /** To request ACM. Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - ACM requested EFI_NOT_FOUND - ACM is unavailable @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardRequestACM ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { // FIT table. ACM length == 0 if (mLocationInfoACM.Address == 0) { return EFI_NOT_FOUND; } *Address = (UINTN)mLocationInfoACM.Address; *Length = (UINTN)mLocationInfoACM.Length; if (*Length == 0 || *Length < sizeof (ACM_HEADER)) { *Length = sizeof (ACM_HEADER); } *FurtherDataRequired = TRUE; *Repeat = FALSE; return EFI_SUCCESS; } /** To check ACMSVN. Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - ACMSVN is valid EFI_SECURITY_VIOLATION - ACMSVN is invalid EFI_UNSUPPORTED - Revocation values are unavailable @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardCheckACMSVN ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { EFI_STATUS Status; ACM_HEADER *ACMH; REVOCATION_VALUE Revocation; UINTN Size; ACMH = (ACM_HEADER *)((UINTN)(*Address)); // // Restore ACM SVN value from LockBox. // Size = sizeof (Revocation); Status = RestoreLockBox (&gArbSvnInfoGuid, &Revocation, &Size); if (EFI_ERROR (Status)) { Status = EFI_NOT_FOUND; } else { if (ACMH->AcmSvn < Revocation.ACMSVN) { Status = EFI_SECURITY_VIOLATION; } } *FurtherDataRequired = FALSE; *Repeat = FALSE; return Status; } /** To find KM. Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - KM is found, or to request the next block EFI_NOT_FOUND - KM is unavailable EFI_UNSUPPORTED - KMID is unavailable @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardFindKM ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { EFI_STATUS Status; KEY_MANIFEST *KM; UINT8 KMID; REVOCATION_VALUE Revocation; UINTN Size; KM = NULL; KMID = 0; Status = BootGuardPlatformLibGetKMID (&KMID); if (EFI_ERROR (Status)) { // // Restore KMID value from LockBox. // Size = sizeof (Revocation); Status = RestoreLockBox (&gArbSvnInfoGuid, &Revocation, &Size); if (EFI_ERROR (Status)) { Status = EFI_NOT_FOUND; } else { KMID = Revocation.KMID; } } if (!EFI_ERROR (Status)) { if (mLocationInfoListKM == NULL) { Status = EFI_NOT_FOUND; } } if (!EFI_ERROR (Status)) { if (mCurrentLocationInfoListKM == NULL) { mCurrentLocationInfoListKM = mLocationInfoListKM; } else { KM = (KEY_MANIFEST *)((UINTN)(*Address)); Status = BootGuardPlatformLibValidateKMStructureID (KM); if (!EFI_ERROR (Status)) { if (KM->KeyManifestId == KMID) { *FurtherDataRequired = FALSE; *Repeat = FALSE; return Status; } } Status = EFI_SUCCESS; if (mCurrentLocationInfoListKM->NextPtr == NULL) { Status = EFI_NOT_FOUND; } mCurrentLocationInfoListKM = mCurrentLocationInfoListKM->NextPtr; } } if (EFI_ERROR (Status)) { *FurtherDataRequired = FALSE; *Repeat = FALSE; return Status; } *Address = (UINTN)mCurrentLocationInfoListKM->LocationInfo.Address; *Length = (UINTN)mCurrentLocationInfoListKM->LocationInfo.Length; *FurtherDataRequired = TRUE; *Repeat = TRUE; return Status; } /** To check KMSVN. Arguments : Address - Address of the input buffer, or of the requesting data Length - Length of the input buffer, or of the requesting data FurtherDataRequired - Indicate to request further data Repeat - Indicate to enter this function again Returns : EFI_SUCCESS - KMSVN is valid EFI_SECURITY_VIOLATION - KMSVN is invalid EFI_UNSUPPORTED - Revocation values are unavailable @param [in, out] Address Address of the input buffer, or of the requesting data @param [in, out] Length Length of the input buffer, or of the requesting data @param [out] FurtherDataRequired Indicate to request further data @param [out] Repeat Indicate to enter this function again **/ EFI_STATUS ImageCheckBootGuardCheckKMSVN ( IN OUT UINTN *Address, IN OUT UINTN *Length, OUT BOOLEAN *FurtherDataRequired, OUT BOOLEAN *Repeat ) { EFI_STATUS Status; KEY_MANIFEST *KM; REVOCATION_VALUE Revocation; UINTN Size; KM = (KEY_MANIFEST *)((UINTN)(*Address)); // // Restore KM SVN value from LockBox. // Size = sizeof (Revocation); Status = RestoreLockBox (&gArbSvnInfoGuid, &Revocation, &Size); if (EFI_ERROR (Status)) { Status = EFI_NOT_FOUND; } else { if (KM->KmSvn < Revocation.KMSVN) { Status = EFI_SECURITY_VIOLATION; } } *FurtherDataRequired = FALSE; *Repeat = FALSE; return Status; }