/** @file Unit tests for the implementation of DxeImageVerificationLib. Copyright (c) 2025, Yandex. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include extern "C" { #include "Library/MemoryAllocationLib.h" #include #include #include #include "DxeImageVerificationLibGoogleTest.h" } ////////////////////////////////////////////////////////////////////////////// void PrepareCertList ( UINTN Size, UINTN BufferSize, CONST EFI_GUID *SignatureType, CONST UINT8 *Src, EFI_SIGNATURE_LIST *Dst ) { Dst->SignatureListSize = (UINT32)BufferSize; Dst->SignatureSize = (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + Size); Dst->SignatureHeaderSize = 0; CopyGuid (&Dst->SignatureType, SignatureType); EFI_SIGNATURE_DATA *Data = (EFI_SIGNATURE_DATA *)(Dst + 1); CopyGuid (&Data->SignatureOwner, &gEfiGlobalVariableGuid); CopyMem (&Data->SignatureData[0], Src, Size); } void ExpectBeforeHashCheck ( MockUefiBootServicesTableLib &BsMock, MockDevicePathLib &DevicePathMock, MockUefiRuntimeServicesTableLib &RtServicesMock ) { // Skip all checks that are called before hash verification. This also applies // to signed binary files, as no additional mocks are needed before the // signature verification starts. // Do not allocate on stack static UINT8 SetupMode = SECURE_BOOT_MODE_ENABLE; EXPECT_CALL (BsMock, gBS_LocateDevicePath) .Times (3) .WillRepeatedly (testing::Return (EFI_NOT_FOUND)); EXPECT_CALL (DevicePathMock, IsDevicePathEndType) .WillOnce (testing::Return ((BOOLEAN)TRUE)); EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_SECURE_BOOT_MODE_NAME), BufferEq (&gEfiGlobalVariableGuid, sizeof (EFI_GUID)), testing::NotNull (), testing::Pointee (testing::Eq (sizeof (SetupMode))), testing::NotNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (sizeof (SetupMode)), SetArgBuffer<4> (&SetupMode, sizeof (SetupMode)), testing::Return (EFI_SUCCESS) ) ); } void ExpectHashCheckSkip ( MockUefiRuntimeServicesTableLib &RtServicesMock, int n ) { // Here, the cycle and WillOnce are used because InSequence must be specified // in the main function. When using InSequence, Times will retire. for (int i = 0; i < n; i++) { // Return ‘not found’ for DBx to exit from the first // IsSignatureFoundInDatabase EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq ( &gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID) ), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce (testing::Return (EFI_NOT_FOUND)); // IsFound is false, EFI_NOT_FOUND will proceed to the next algorithm EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE), BufferEq ( &gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID) ), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce (testing::Return (EFI_NOT_FOUND)); } } template void ExpectHashDBValue ( MockUefiRuntimeServicesTableLib &RtServicesMock, UINT8 (&CertListBuffer)[N], UINTN BufferSize ) { // Return ‘not found’ for DBx to exit from the first // IsSignatureFoundInDatabase EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce (testing::Return (EFI_NOT_FOUND)); // Second call of IsSignatureFoundInDatabase for DB // Get Size EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (BufferSize), testing::Return (EFI_BUFFER_TOO_SMALL) ) ); // Return hash EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)BufferSize)), testing::NotNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (BufferSize), SetArgBuffer<4> (&CertListBuffer[0], BufferSize), testing::Return (EFI_SUCCESS) ) ); // Hash verification does't exit the loop upon the first match EXPECT_CALL (RtServicesMock, gRT_GetVariable) .Times (testing::AnyNumber ()) .WillRepeatedly (testing::Return (EFI_NOT_FOUND)); } EFI_STATUS MockInstallConfigurationTable ( EFI_GUID *Guid, VOID *Table ) { // LeakSanitizer workaround for AddImageExeInfo if (Table != NULL) { FreePool (Table); } return EFI_SUCCESS; } void ExpectFailureJump ( MockDevicePathLib &DevicePathMock, MockUefiLib &UefiMock, MockUefiBootServicesTableLib &BsMock ) { EXPECT_CALL (DevicePathMock, ConvertDevicePathToText) .WillRepeatedly (testing::Return ((CHAR16 *)NULL)); EXPECT_CALL (UefiMock, EfiGetSystemConfigurationTable) .WillRepeatedly (testing::Return (EFI_SUCCESS)); EXPECT_CALL (DevicePathMock, GetDevicePathSize) .WillRepeatedly (testing::Return ((UINTN)0)); EXPECT_CALL (BsMock, gBS_InstallConfigurationTable) .WillRepeatedly (testing::Invoke (MockInstallConfigurationTable)); } template void ExpectForbiddenByDBxHash ( MockUefiRuntimeServicesTableLib &RtServicesMock, UINT8 (&CertListBuffer)[N], UINTN BufferSize, UINT8 (&HashListBuffer)[M], UINTN HashBufferSize ) { // Signature DBx check - EFI_NOT_FOUND EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce (testing::Return (EFI_NOT_FOUND)); // IsAllowedByDb - DB size check EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (BufferSize), testing::Return (EFI_BUFFER_TOO_SMALL) ) ); // IsAllowedByDb - DB data (X509 certs entries) EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)BufferSize)), testing::NotNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (BufferSize), SetArgBuffer<4> (&CertListBuffer[0], BufferSize), testing::Return (EFI_SUCCESS) ) ); // IsAllowedByDb DBx check root cert revoked EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce (testing::Return (EFI_NOT_FOUND)); // IsSignatureFoundInDatabase prepare buffer EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (HashBufferSize), testing::Return (EFI_BUFFER_TOO_SMALL) ) ); // IsSignatureFoundInDatabase prohibit hash EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)HashBufferSize)), testing::NotNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (HashBufferSize), SetArgBuffer<4> (&HashListBuffer[0], HashBufferSize), testing::Return (EFI_SUCCESS) ) ); EXPECT_CALL (RtServicesMock, gRT_GetVariable) .Times (testing::AnyNumber ()) .WillRepeatedly (testing::Return (EFI_NOT_FOUND)); } template void ExpectNoSignatureHashDBValue ( MockUefiRuntimeServicesTableLib &RtServicesMock, UINT8 (&HashCertListBuffer)[N], UINTN HashBufferSize ) { // Signature DBx check - EFI_NOT_FOUND EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce (testing::Return (EFI_NOT_FOUND)); // IsAllowedByDb - DB size check EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE), BufferEq ( &gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID) ), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (HashBufferSize), testing::Return (EFI_BUFFER_TOO_SMALL) ) ); // IsAllowedByDb - DB data (hash entries, no X509 certs) EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE), BufferEq ( &gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID) ), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)HashBufferSize)), testing::NotNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (HashBufferSize), SetArgBuffer<4> (&HashCertListBuffer[0], HashBufferSize), testing::Return (EFI_SUCCESS) ) ); // IsAllowedByDb (DBX) - NOT FOUND EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce (testing::Return (EFI_NOT_FOUND)); // IsSignatureFoundInDatabase (DBX) - NOT FOUND EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce (testing::Return (EFI_NOT_FOUND)); // IsSignatureFoundInDatabase (DB) - size check EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (HashBufferSize), testing::Return (EFI_BUFFER_TOO_SMALL) ) ); // IsSignatureFoundInDatabase (DB) - data (hash found) EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)HashBufferSize)), testing::NotNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (HashBufferSize), SetArgBuffer<4> (&HashCertListBuffer[0], HashBufferSize), testing::Return (EFI_SUCCESS) ) ); EXPECT_CALL (RtServicesMock, gRT_GetVariable) .Times (testing::AnyNumber ()) .WillRepeatedly (testing::Return (EFI_NOT_FOUND)); } template void ExpectCertForbiddenByDbx ( MockUefiRuntimeServicesTableLib &RtServicesMock, UINT8 (&CertListBuffer)[N], UINTN BufferSize ) { EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (BufferSize), testing::Return (EFI_BUFFER_TOO_SMALL) ) ); EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)BufferSize)), testing::NotNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (BufferSize), SetArgBuffer<4> (&CertListBuffer[0], BufferSize), testing::Return (EFI_SUCCESS) ) ); } ////////////////////////////////////////////////////////////////////////////// class CheckImageTypeResult : public ::testing::Test { public: EFI_DEVICE_PATH_PROTOCOL File; protected: MockUefiRuntimeServicesTableLib RtServicesMock; MockUefiBootServicesTableLib BsMock; MockDevicePathLib DevicePathMock; EFI_STATUS Status; UINT32 AuthenticationStatus; VOID *FileBuffer; UINTN FileSize; BOOLEAN BootPolicy; virtual void SetUp ( ) { AuthenticationStatus = 0; FileBuffer = NULL; FileSize = 0; BootPolicy = FALSE; } }; TEST_F (CheckImageTypeResult, ImageTypeVerifySanity) { // Sanity check Status = DxeImageVerificationHandler ( AuthenticationStatus, NULL, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_INVALID_PARAMETER); } TEST_F (CheckImageTypeResult, ImageTypeVerifyImageFromFv) { EXPECT_CALL (BsMock, gBS_LocateDevicePath) .WillRepeatedly (testing::Return (EFI_SUCCESS)); EXPECT_CALL (BsMock, gBS_OpenProtocol) .WillRepeatedly (testing::Return (EFI_SUCCESS)); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } TEST_F (CheckImageTypeResult, ImageTypeVerifyImageFromOptionRom) { auto TestFunc = [&] (EFI_STATUS ExpectedStatus) { EXPECT_CALL (BsMock, gBS_LocateDevicePath) .Times (3) .WillRepeatedly (testing::Return (EFI_NOT_FOUND)); EXPECT_CALL (BsMock, gBS_OpenProtocol) .WillRepeatedly (testing::Return (EFI_NOT_FOUND)); EXPECT_CALL (DevicePathMock, IsDevicePathEndType) .WillOnce (testing::Return ((BOOLEAN)FALSE)); EXPECT_CALL (DevicePathMock, DevicePathType) .WillOnce (testing::Return ((UINT8)MEDIA_DEVICE_PATH)); EXPECT_CALL (DevicePathMock, DevicePathSubType) .WillOnce (testing::Return ((UINT8)MEDIA_RELATIVE_OFFSET_RANGE_DP)); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, ExpectedStatus); }; PatchPcdSet32 (PcdOptionRomImageVerificationPolicy, ALWAYS_EXECUTE); TestFunc (EFI_SUCCESS); PatchPcdSet32 (PcdOptionRomImageVerificationPolicy, NEVER_EXECUTE); TestFunc (EFI_ACCESS_DENIED); } TEST_F (CheckImageTypeResult, ImageTypeVerifyImageFromRemovableMedia) { auto TestFunc = [&] (EFI_STATUS ExpectedStatus) { EXPECT_CALL (BsMock, gBS_LocateDevicePath) .Times (3) .WillRepeatedly (testing::Return (EFI_NOT_FOUND)); EXPECT_CALL (DevicePathMock, IsDevicePathEndType) .WillOnce (testing::Return ((BOOLEAN)FALSE)); EXPECT_CALL (DevicePathMock, DevicePathType) .WillOnce (testing::Return ((UINT8)MESSAGING_DEVICE_PATH)); EXPECT_CALL (DevicePathMock, DevicePathSubType) .WillOnce (testing::Return ((UINT8)MSG_MAC_ADDR_DP)); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, ExpectedStatus); }; PatchPcdSet32 (PcdRemovableMediaImageVerificationPolicy, ALWAYS_EXECUTE); TestFunc (EFI_SUCCESS); PatchPcdSet32 (PcdRemovableMediaImageVerificationPolicy, NEVER_EXECUTE); TestFunc (EFI_ACCESS_DENIED); } TEST_F (CheckImageTypeResult, ImageTypeVerifyImageFromFixedMedia) { auto TestFunc = [&] (EFI_STATUS ExpectedStatus) { EXPECT_CALL (BsMock, gBS_LocateDevicePath) .WillOnce (testing::Return (EFI_NOT_FOUND)) .WillOnce (testing::Return (EFI_NOT_FOUND)) .WillOnce (testing::Return (EFI_SUCCESS)); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, ExpectedStatus); }; PatchPcdSet32 (PcdFixedMediaImageVerificationPolicy, ALWAYS_EXECUTE); TestFunc (EFI_SUCCESS); PatchPcdSet32 (PcdFixedMediaImageVerificationPolicy, NEVER_EXECUTE); TestFunc (EFI_ACCESS_DENIED); } ////////////////////////////////////////////////////////////////////////////// class CheckUnsignedImage : public ::testing::Test { public: EFI_DEVICE_PATH_PROTOCOL File; protected: MockUefiRuntimeServicesTableLib RtServicesMock; MockUefiBootServicesTableLib BsMock; MockDevicePathLib DevicePathMock; MockUefiLib UefiMock; EFI_STATUS Status; UINT32 AuthenticationStatus; VOID *FileBuffer; UINTN FileSize; BOOLEAN BootPolicy; virtual void SetUp ( ) { AuthenticationStatus = 0; FileBuffer = NULL; FileSize = 0; BootPolicy = FALSE; } }; TEST_F (CheckUnsignedImage, HashNormalFlow) { constexpr UINTN Hash512Size = sizeof (images::UnsignedCOFFSha512); constexpr UINTN Hash384Size = sizeof (images::UnsignedCOFFSha384); constexpr UINTN Hash256Size = sizeof (images::UnsignedCOFFSha256); constexpr UINTN Hash1Size = sizeof (images::UnsignedCOFFSha1); constexpr UINTN Hash512BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash512Size; constexpr UINTN Hash384BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash384Size; constexpr UINTN Hash256BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash256Size; constexpr UINTN Hash1BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash1Size; UINT8 Hash512CertListBuffer[Hash512BufferSize] = { 0 }; UINT8 Hash384CertListBuffer[Hash384BufferSize] = { 0 }; UINT8 Hash256CertListBuffer[Hash256BufferSize] = { 0 }; UINT8 Hash1CertListBuffer[Hash1BufferSize] = { 0 }; PrepareCertList ( Hash512Size, Hash512BufferSize, &gEfiCertSha512Guid, &images::UnsignedCOFFSha512[0], (EFI_SIGNATURE_LIST *)&Hash512CertListBuffer ); { // Do not delete this. Otherwise, GetVariable from ExpectHashDBValue will // match all calls. testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectHashDBValue ( RtServicesMock, Hash512CertListBuffer, Hash512BufferSize ); FileBuffer = (VOID *)&images::UnsignedCOFF; FileSize = sizeof (images::UnsignedCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } PrepareCertList ( Hash384Size, Hash384BufferSize, &gEfiCertSha384Guid, &images::UnsignedCOFFSha384[0], (EFI_SIGNATURE_LIST *)&Hash384CertListBuffer ); { // Do not delete this. Otherwise, GetVariable from ExpectHashDBValue will // match all calls. testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); // Skip SHA512 check ExpectHashCheckSkip (RtServicesMock, 1); // SHA384 check ExpectHashDBValue ( RtServicesMock, Hash384CertListBuffer, Hash384BufferSize ); FileBuffer = (VOID *)&images::UnsignedCOFF; FileSize = sizeof (images::UnsignedCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } PrepareCertList ( Hash256Size, Hash256BufferSize, &gEfiCertSha256Guid, &images::UnsignedCOFFSha256[0], (EFI_SIGNATURE_LIST *)&Hash256CertListBuffer ); { // Do not delete this. Otherwise, GetVariable from ExpectHashDBValue will // match all calls. testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); // Skip SHA512, SHA384 check ExpectHashCheckSkip (RtServicesMock, 2); // SHA256 check ExpectHashDBValue ( RtServicesMock, Hash256CertListBuffer, Hash256BufferSize ); FileBuffer = (VOID *)&images::UnsignedCOFF; FileSize = sizeof (images::UnsignedCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } PrepareCertList ( Hash1Size, Hash1BufferSize, &gEfiCertSha1Guid, &images::UnsignedCOFFSha1[0], (EFI_SIGNATURE_LIST *)&Hash1CertListBuffer ); { // Do not delete this. Otherwise, GetVariable from ExpectHashDBValue will // match all calls. testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); // Skip SHA512, SHA384, SHA256 check ExpectHashCheckSkip (RtServicesMock, 3); ExpectHashDBValue ( RtServicesMock, Hash1CertListBuffer, Hash1BufferSize ); // Last check. No need to loop. FileBuffer = (VOID *)&images::UnsignedCOFF; FileSize = sizeof (images::UnsignedCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } } TEST_F (CheckUnsignedImage, HashNoDBRecods) { // Do not delete this. Otherwise, GetVariable from ExpectHashDBValue will // match all calls. testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); // Skip SHA512, SHA384, SHA256, SHA1 check ExpectHashCheckSkip (RtServicesMock, 4); ExpectFailureJump (DevicePathMock, UefiMock, BsMock); // Last check. No need to loop. FileBuffer = (VOID *)&images::UnsignedCOFF; FileSize = sizeof (images::UnsignedCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_ACCESS_DENIED); } TEST_F (CheckUnsignedImage, HashFoundDBx) { constexpr UINTN Size = sizeof (images::UnsignedCOFFSha512); constexpr UINTN BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Size; UINT8 CertListBuffer[BufferSize] = { 0 }; PrepareCertList ( Size, BufferSize, &gEfiCertSha512Guid, &images::UnsignedCOFFSha512[0], (EFI_SIGNATURE_LIST *)&CertListBuffer ); // Do not delete this. Otherwise, GetVariable from ExpectHashDBValue will // match all calls. testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); // DBx routines EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)0)), testing::IsNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (BufferSize), testing::Return (EFI_BUFFER_TOO_SMALL) ) ); // Return hash EXPECT_CALL ( RtServicesMock, gRT_GetVariable ( Char16StrEq (EFI_IMAGE_SECURITY_DATABASE1), BufferEq (&gEfiImageSecurityDatabaseGuid, sizeof (EFI_GUID)), testing::IsNull (), testing::Pointee (testing::Eq ((UINTN)BufferSize)), testing::NotNull () ) ) .WillOnce ( testing::DoAll ( testing::SetArgPointee<3> (BufferSize), SetArgBuffer<4> (&CertListBuffer[0], BufferSize), testing::Return (EFI_SUCCESS) ) ); ExpectFailureJump (DevicePathMock, UefiMock, BsMock); // Last check. No need to loop. FileBuffer = (VOID *)&images::UnsignedCOFF; FileSize = sizeof (images::UnsignedCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_ACCESS_DENIED); } ////////////////////////////////////////////////////////////////////////////// class CheckSignedImage : public ::testing::Test { public: EFI_DEVICE_PATH_PROTOCOL File; protected: MockUefiRuntimeServicesTableLib RtServicesMock; MockUefiBootServicesTableLib BsMock; MockDevicePathLib DevicePathMock; MockUefiLib UefiMock; EFI_STATUS Status; UINT32 AuthenticationStatus; VOID *FileBuffer; UINTN FileSize; BOOLEAN BootPolicy; virtual void SetUp ( ) { AuthenticationStatus = 0; FileBuffer = NULL; FileSize = 0; BootPolicy = FALSE; } }; TEST_F (CheckSignedImage, NormalFlowPkcs7) { constexpr UINTN CertSize = sizeof (certs::TestCertDer); constexpr UINTN BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + CertSize; UINT8 CertListBuffer[BufferSize] = { 0 }; PrepareCertList ( CertSize, BufferSize, &gEfiCertX509Guid, &certs::TestCertDer[0], (EFI_SIGNATURE_LIST *)&CertListBuffer ); // Do not delete this. Otherwise, GetVariable from ExpectSignatureFoundInDb // will match all calls. testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectHashDBValue (RtServicesMock, CertListBuffer, BufferSize); FileBuffer = (VOID *)&images::PkcsCOFF; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } TEST_F (CheckSignedImage, NormalFlowUefiGuid) { constexpr UINTN CertSize = sizeof (certs::TestCertDer); constexpr UINTN BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + CertSize; UINT8 CertListBuffer[BufferSize] = { 0 }; PrepareCertList ( CertSize, BufferSize, &gEfiCertX509Guid, &certs::TestCertDer[0], (EFI_SIGNATURE_LIST *)&CertListBuffer ); // Do not delete this. Otherwise, GetVariable from ExpectSignatureFoundInDb // will match all calls. testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectHashDBValue (RtServicesMock, CertListBuffer, BufferSize); FileBuffer = (VOID *)&images::CertGuidCOFF; FileSize = sizeof (images::CertGuidCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } TEST_F (CheckSignedImage, NormalFlowTwoCerts) { constexpr UINTN CertSize = sizeof (certs::TestCertDer); constexpr UINTN SignatureDataSize = sizeof (EFI_GUID) + CertSize; constexpr UINTN BufferSize = sizeof (EFI_SIGNATURE_LIST) + (SignatureDataSize * 2); UINT8 CertListBuffer[BufferSize] = { 0 }; UINT8 InvalidCert[CertSize] = { 0 }; CopyMem (InvalidCert, certs::TestCertDer, CertSize); InvalidCert[0] = 0xAA; EFI_SIGNATURE_LIST *CertList = (EFI_SIGNATURE_LIST *)&CertListBuffer; CertList->SignatureListSize = (UINT32)BufferSize; CertList->SignatureHeaderSize = 0; CertList->SignatureSize = (UINT32)SignatureDataSize; CopyGuid (&CertList->SignatureType, &gEfiCertX509Guid); EFI_SIGNATURE_DATA *Cert1 = (EFI_SIGNATURE_DATA *)(CertList + 1); CopyGuid (&Cert1->SignatureOwner, &gEfiGlobalVariableGuid); CopyMem (Cert1->SignatureData, InvalidCert, CertSize); EFI_SIGNATURE_DATA *Cert2 = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert1 + SignatureDataSize); CopyGuid (&Cert2->SignatureOwner, &gEfiGlobalVariableGuid); CopyMem (Cert2->SignatureData, certs::TestCertDer, CertSize); testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectHashDBValue (RtServicesMock, CertListBuffer, BufferSize); FileBuffer = (VOID *)&images::PkcsCOFF; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } void UpdatePeAuthCodeHash ( UINT8 *PkcsCopy, UINT32 HashType, CONST UINT8 *HashValue, UINTN HashSize ) { constexpr UINTN HashOidOffset = 0x408; // AuthData(0x3e8) + 32 constexpr UINTN HashTagOffset = 0x470; // AuthData + 132 constexpr UINTN HashValueOffset = 0x472; // AuthData + 134 static const UINT8 OidSha1[] = { 0x2B, 0x0E, 0x03, 0x02, 0x1A }; static const UINT8 OidSha256[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 }; static const UINT8 OidSha384[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 }; static const UINT8 OidSha512[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 }; const UINT8 *Oid; UINTN OidLength; switch (HashType) { case HASHALG_SHA1: Oid = OidSha1; OidLength = sizeof (OidSha1); break; case HASHALG_SHA256: Oid = OidSha256; OidLength = sizeof (OidSha256); break; case HASHALG_SHA384: Oid = OidSha384; OidLength = sizeof (OidSha384); break; case HASHALG_SHA512: Oid = OidSha512; OidLength = sizeof (OidSha512); break; default: return; } CopyMem (PkcsCopy + HashOidOffset, Oid, OidLength); PkcsCopy[HashTagOffset] = 0x04; // ASN.1 Octet(value 0x04) string PkcsCopy[HashTagOffset + 1] = (UINT8)HashSize; CopyMem (PkcsCopy + HashValueOffset, HashValue, HashSize); } TEST_F (CheckSignedImage, NormalFlowPkcsNoCertHashAllowed) { constexpr UINTN Hash512Size = sizeof (images::PkcsCOFFSha512); constexpr UINTN Hash384Size = sizeof (images::PkcsCOFFSha384); constexpr UINTN Hash256Size = sizeof (images::PkcsCOFFSha256); constexpr UINTN Hash1Size = sizeof (images::PkcsCOFFSha1); constexpr UINTN Hash512BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash512Size; constexpr UINTN Hash384BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash384Size; constexpr UINTN Hash256BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash256Size; constexpr UINTN Hash1BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash1Size; UINT8 Hash512CertListBuffer[Hash512BufferSize] = { 0 }; UINT8 Hash384CertListBuffer[Hash384BufferSize] = { 0 }; UINT8 Hash256CertListBuffer[Hash256BufferSize] = { 0 }; UINT8 Hash1CertListBuffer[Hash1BufferSize] = { 0 }; UINT8 PkcsSha1Copy[sizeof (images::PkcsCOFF)]; UINT8 PkcsSha256Copy[sizeof (images::PkcsCOFF)]; UINT8 PkcsSha384Copy[sizeof (images::PkcsCOFF)]; UINT8 PkcsSha512Copy[sizeof (images::PkcsCOFF)]; CopyMem (PkcsSha1Copy, images::PkcsCOFF, sizeof (images::PkcsCOFF)); CopyMem (PkcsSha256Copy, images::PkcsCOFF, sizeof (images::PkcsCOFF)); CopyMem (PkcsSha384Copy, images::PkcsCOFF, sizeof (images::PkcsCOFF)); CopyMem (PkcsSha512Copy, images::PkcsCOFF, sizeof (images::PkcsCOFF)); UpdatePeAuthCodeHash (PkcsSha1Copy, HASHALG_SHA1, images::PkcsCOFFSha1, Hash1Size); UpdatePeAuthCodeHash (PkcsSha256Copy, HASHALG_SHA256, images::PkcsCOFFSha256, Hash256Size); UpdatePeAuthCodeHash (PkcsSha384Copy, HASHALG_SHA384, images::PkcsCOFFSha384, Hash384Size); UpdatePeAuthCodeHash (PkcsSha512Copy, HASHALG_SHA512, images::PkcsCOFFSha512, Hash512Size); PrepareCertList ( Hash512Size, Hash512BufferSize, &gEfiCertSha512Guid, &images::PkcsCOFFSha512[0], (EFI_SIGNATURE_LIST *)&Hash512CertListBuffer ); { testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectNoSignatureHashDBValue ( RtServicesMock, Hash512CertListBuffer, Hash512BufferSize ); FileBuffer = (VOID *)&PkcsSha512Copy; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } PrepareCertList ( Hash384Size, Hash384BufferSize, &gEfiCertSha384Guid, &images::PkcsCOFFSha384[0], (EFI_SIGNATURE_LIST *)&Hash384CertListBuffer ); { testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectNoSignatureHashDBValue ( RtServicesMock, Hash384CertListBuffer, Hash384BufferSize ); FileBuffer = (VOID *)&PkcsSha384Copy; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } PrepareCertList ( Hash256Size, Hash256BufferSize, &gEfiCertSha256Guid, &images::PkcsCOFFSha256[0], (EFI_SIGNATURE_LIST *)&Hash256CertListBuffer ); { testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectNoSignatureHashDBValue ( RtServicesMock, Hash256CertListBuffer, Hash256BufferSize ); FileBuffer = (VOID *)&PkcsSha256Copy; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } PrepareCertList ( Hash1Size, Hash1BufferSize, &gEfiCertSha1Guid, &images::PkcsCOFFSha1[0], (EFI_SIGNATURE_LIST *)&Hash1CertListBuffer ); { testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectNoSignatureHashDBValue ( RtServicesMock, Hash1CertListBuffer, Hash1BufferSize ); FileBuffer = (VOID *)&PkcsSha1Copy; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_SUCCESS); } } TEST_F (CheckSignedImage, ForbiddenByDbxPkcs7Sign) { constexpr UINTN CertSize = sizeof (certs::TestCertDer); constexpr UINTN BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + CertSize; UINT8 CertListBuffer[BufferSize] = { 0 }; PrepareCertList ( CertSize, BufferSize, &gEfiCertX509Guid, &certs::TestCertDer[0], (EFI_SIGNATURE_LIST *)&CertListBuffer ); // Do not delete this. Otherwise, GetVariable from ExpectCertForbiddenByDbx // will match all calls. testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectCertForbiddenByDbx ( RtServicesMock, CertListBuffer, BufferSize ); ExpectFailureJump (DevicePathMock, UefiMock, BsMock); FileBuffer = (VOID *)&images::PkcsCOFF; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_ACCESS_DENIED); } TEST_F (CheckSignedImage, ForbiddenByDbxUefiGuidSign) { constexpr UINTN CertSize = sizeof (certs::TestCertDer); constexpr UINTN BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + CertSize; UINT8 CertListBuffer[BufferSize] = { 0 }; PrepareCertList ( CertSize, BufferSize, &gEfiCertX509Guid, &certs::TestCertDer[0], (EFI_SIGNATURE_LIST *)&CertListBuffer ); // Do not delete this. Otherwise, GetVariable from ExpectCertForbiddenByDbx // will match all calls. testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectCertForbiddenByDbx ( RtServicesMock, CertListBuffer, BufferSize ); ExpectFailureJump (DevicePathMock, UefiMock, BsMock); FileBuffer = (VOID *)&images::CertGuidCOFF; FileSize = sizeof (images::CertGuidCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_ACCESS_DENIED); } TEST_F (CheckSignedImage, NoCertPkcs7SignNoHash) { // This test also covers the code path for when a perfectly valid signature is // missing from the 'db' variable, resulting in the error: "Image is signed // but signature is not allowed by DB and %s hash of image is not found in // DB/DBX." constexpr UINTN CertSize = sizeof (certs::TestCertDer); constexpr UINTN BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + CertSize; UINT8 InvalidCert[CertSize] = { 0 }; CopyMem (InvalidCert, images::PkcsCOFF, CertSize); InvalidCert[0] = 0xAA; UINT8 CertListBuffer[BufferSize] = { 0 }; PrepareCertList ( CertSize, BufferSize, &gEfiCertX509Guid, InvalidCert, (EFI_SIGNATURE_LIST *)&CertListBuffer ); testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectHashDBValue (RtServicesMock, CertListBuffer, BufferSize); ExpectFailureJump (DevicePathMock, UefiMock, BsMock); FileBuffer = (VOID *)&images::PkcsCOFF; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_ACCESS_DENIED); } TEST_F (CheckSignedImage, ForbiddenByDBxHash) { constexpr UINTN CertSize = sizeof (certs::TestCertDer); constexpr UINTN Hash512Size = sizeof (images::PkcsCOFFSha512); constexpr UINTN Hash384Size = sizeof (images::PkcsCOFFSha384); constexpr UINTN Hash256Size = sizeof (images::PkcsCOFFSha256); constexpr UINTN Hash1Size = sizeof (images::PkcsCOFFSha1); constexpr UINTN BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + CertSize; constexpr UINTN Hash512BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash512Size; constexpr UINTN Hash384BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash384Size; constexpr UINTN Hash256BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash256Size; constexpr UINTN Hash1BufferSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Hash1Size; UINT8 CertListBuffer[BufferSize] = { 0 }; UINT8 Hash512CertListBuffer[Hash512BufferSize] = { 0 }; UINT8 Hash384CertListBuffer[Hash384BufferSize] = { 0 }; UINT8 Hash256CertListBuffer[Hash256BufferSize] = { 0 }; UINT8 Hash1CertListBuffer[Hash1BufferSize] = { 0 }; UINT8 PkcsSha1Copy[sizeof (images::PkcsCOFF)]; UINT8 PkcsSha256Copy[sizeof (images::PkcsCOFF)]; UINT8 PkcsSha384Copy[sizeof (images::PkcsCOFF)]; UINT8 PkcsSha512Copy[sizeof (images::PkcsCOFF)]; CopyMem (PkcsSha1Copy, images::PkcsCOFF, sizeof (images::PkcsCOFF)); CopyMem (PkcsSha256Copy, images::PkcsCOFF, sizeof (images::PkcsCOFF)); CopyMem (PkcsSha384Copy, images::PkcsCOFF, sizeof (images::PkcsCOFF)); CopyMem (PkcsSha512Copy, images::PkcsCOFF, sizeof (images::PkcsCOFF)); UpdatePeAuthCodeHash (PkcsSha1Copy, HASHALG_SHA1, images::PkcsCOFFSha1, Hash1Size); UpdatePeAuthCodeHash (PkcsSha256Copy, HASHALG_SHA256, images::PkcsCOFFSha256, Hash256Size); UpdatePeAuthCodeHash (PkcsSha384Copy, HASHALG_SHA384, images::PkcsCOFFSha384, Hash384Size); UpdatePeAuthCodeHash (PkcsSha512Copy, HASHALG_SHA512, images::PkcsCOFFSha512, Hash512Size); PrepareCertList ( CertSize, BufferSize, &gEfiCertX509Guid, certs::TestCertDer, (EFI_SIGNATURE_LIST *)&CertListBuffer ); PrepareCertList ( Hash512Size, Hash512BufferSize, &gEfiCertSha512Guid, &images::PkcsCOFFSha512[0], (EFI_SIGNATURE_LIST *)&Hash512CertListBuffer ); { testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectForbiddenByDBxHash ( RtServicesMock, CertListBuffer, BufferSize, Hash512CertListBuffer, Hash512BufferSize ); ExpectFailureJump (DevicePathMock, UefiMock, BsMock); FileBuffer = (VOID *)&PkcsSha512Copy; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_ACCESS_DENIED); } PrepareCertList ( Hash384Size, Hash384BufferSize, &gEfiCertSha384Guid, &images::PkcsCOFFSha384[0], (EFI_SIGNATURE_LIST *)&Hash384CertListBuffer ); { testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectForbiddenByDBxHash ( RtServicesMock, CertListBuffer, BufferSize, Hash384CertListBuffer, Hash384BufferSize ); ExpectFailureJump (DevicePathMock, UefiMock, BsMock); FileBuffer = (VOID *)&PkcsSha384Copy; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_ACCESS_DENIED); } PrepareCertList ( Hash256Size, Hash256BufferSize, &gEfiCertSha256Guid, &images::PkcsCOFFSha256[0], (EFI_SIGNATURE_LIST *)&Hash256CertListBuffer ); { testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectForbiddenByDBxHash ( RtServicesMock, CertListBuffer, BufferSize, Hash256CertListBuffer, Hash256BufferSize ); ExpectFailureJump (DevicePathMock, UefiMock, BsMock); FileBuffer = (VOID *)&PkcsSha256Copy; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_ACCESS_DENIED); } PrepareCertList ( Hash1Size, Hash1BufferSize, &gEfiCertSha1Guid, &images::PkcsCOFFSha1[0], (EFI_SIGNATURE_LIST *)&Hash1CertListBuffer ); { testing::InSequence s; ExpectBeforeHashCheck (BsMock, DevicePathMock, RtServicesMock); ExpectForbiddenByDBxHash ( RtServicesMock, CertListBuffer, BufferSize, Hash1CertListBuffer, Hash1BufferSize ); ExpectFailureJump (DevicePathMock, UefiMock, BsMock); FileBuffer = (VOID *)&PkcsSha1Copy; FileSize = sizeof (images::PkcsCOFF); Status = DxeImageVerificationHandler ( AuthenticationStatus, &File, FileBuffer, FileSize, BootPolicy ); EXPECT_EQ (Status, EFI_ACCESS_DENIED); } } int main ( int argc, char *argv[] ) { testing::InitGoogleTest (&argc, argv); return RUN_ALL_TESTS (); }