SecurityPkg: Added basic DxeImageVerificationLib tests

Add initial unit test for DxeImageVerificationHandler to
validate signature verification bypass for selected image types.

Signed-off-by: Alexander Gryanko <xpahos@gmail.com>
This commit is contained in:
Alexander Gryanko 2025-06-22 15:38:43 +03:00 committed by mergify[bot]
parent 5125e2d6b1
commit 057a611ae6
5 changed files with 322 additions and 0 deletions

View File

@ -1704,6 +1704,13 @@ DxeImageVerificationHandler (
IsFound = FALSE;
IsFoundInDatabase = FALSE;
//
// Sanity check
//
if (File == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Check the image type and get policy setting.
//

View File

@ -0,0 +1,137 @@
/** @file
Unit tests for the implementation of DxeImageVerificationLib.
Copyright (c) 2025, Yandex. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/GoogleTestLib.h>
#include <GoogleTest/Library/MockUefiLib.h>
#include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h>
#include <GoogleTest/Library/MockUefiBootServicesTableLib.h>
#include <GoogleTest/Library/MockDevicePathLib.h>
extern "C" {
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include "DxeImageVerificationLibGoogleTest.h"
}
//////////////////////////////////////////////////////////////////////////////
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);
}
int
main (
int argc,
char *argv[]
)
{
testing::InitGoogleTest (&argc, argv);
return RUN_ALL_TESTS ();
}

View File

@ -0,0 +1,79 @@
/** @file
Unit tests for the implementation of DxeImageVerificationLib.
Copyright (c) 2025, Yandex. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef DXE_IMAGE_VERIFICATION_LIB_GOOGLE_TEST_H
#define DXE_IMAGE_VERIFICATION_LIB_GOOGLE_TEST_H
/**
Provide verification service for signed images, which include both signature validation
and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and
MSFT Authenticode type signatures are supported.
In this implementation, only verify external executables when in USER MODE.
Executables from FV is bypass, so pass in AuthenticationStatus is ignored.
The image verification policy is:
If the image is signed,
At least one valid signature or at least one hash value of the image must match a record
in the security database "db", and no valid signature nor any hash value of the image may
be reflected in the security database "dbx".
Otherwise, the image is not signed,
The hash value of the image must match a record in the security database "db", and
not be reflected in the security data base "dbx".
Caution: This function may receive untrusted input.
PE/COFF image is external input, so this function will validate its data structure
within this image buffer before use.
@param[in] AuthenticationStatus
This is the authentication status returned from the security
measurement services for the input file.
@param[in] File This is a pointer to the device path of the file that is
being dispatched. This will optionally be used for logging.
@param[in] FileBuffer File buffer matches the input file device path.
@param[in] FileSize Size of File buffer matches the input file device path.
@param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service.
@retval EFI_SUCCESS The file specified by DevicePath and non-NULL
FileBuffer did authenticate, and the platform policy dictates
that the DXE Foundation may use the file.
@retval EFI_SUCCESS The device path specified by NULL device path DevicePath
and non-NULL FileBuffer did authenticate, and the platform
policy dictates that the DXE Foundation may execute the image in
FileBuffer.
@retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
the platform policy dictates that File should be placed
in the untrusted state. The image has been added to the file
execution table.
@retval EFI_ACCESS_DENIED The file specified by File and FileBuffer did not
authenticate, and the platform policy dictates that the DXE
Foundation may not use File. The image has
been added to the file execution table.
**/
EFI_STATUS
EFIAPI
DxeImageVerificationHandler (
IN UINT32 AuthenticationStatus,
IN CONST EFI_DEVICE_PATH_PROTOCOL *File OPTIONAL,
IN VOID *FileBuffer,
IN UINTN FileSize,
IN BOOLEAN BootPolicy
);
//
// The DxeImageVerificationLib.h file has dependencies on Pi/PiFirmwareVolume.h and Pi/PiFirmwareFile.h.
// These macros are copied from the header file to prevent PiPei.h from being included in HOST_APPLICATION.
//
//
// Authorization policy bit definition
//
#define ALWAYS_EXECUTE 0x00000000
#define NEVER_EXECUTE 0x00000001
#endif // DXE_IMAGE_VERIFICATION_LIB_GOOGLE_TEST_H

View File

@ -0,0 +1,79 @@
## @file
# Unit test suite for the DxeImageVerificationLib using Google Test
#
# Copyright (c) 2025, Yandex. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = DxeImageVerificationLibGoogleTest
FILE_GUID = 18723239-55AA-4814-9B7A-874BAF719A65
MODULE_TYPE = HOST_APPLICATION
VERSION_STRING = 1.0
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
DxeImageVerificationLibGoogleTest.cpp
../../../../MdePkg/Test/Mock/Library/GoogleTest/Protocol/MockRng.cpp
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
SecurityPkg/SecurityPkg.dec
UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
DxeImageVerificationLib
GoogleTestLib
BaseCryptLib
DebugLib
[Guids]
## SOMETIMES_CONSUMES ## Variable:L"SecureBoot"
gEfiGlobalVariableGuid
## SOMETIMES_CONSUMES ## Variable:L"DB"
## SOMETIMES_CONSUMES ## Variable:L"DBX"
## SOMETIMES_CONSUMES ## Variable:L"DBT"
## PRODUCES ## SystemTable
## CONSUMES ## SystemTable
gEfiImageSecurityDatabaseGuid
## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature.
gEfiCertSha1Guid
## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature.
gEfiCertSha256Guid
## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature.
gEfiCertSha384Guid
## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature.
gEfiCertSha512Guid
gEfiCertX509Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
gEfiCertX509Sha256Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
gEfiCertX509Sha384Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
gEfiCertX509Sha512Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature.
gEfiCertPkcs7Guid ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the certificate.
[Protocols]
gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMES
gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES
gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
[Pcd]
gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy ## SOMETIMES_CONSUMES
gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy ## SOMETIMES_CONSUMES
gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy ## SOMETIMES_CONSUMES

View File

@ -46,3 +46,23 @@
PlatformPKProtectionLib|SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf
UefiLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.inf
}
SecurityPkg/Library/DxeImageVerificationLib/GoogleTest/DxeImageVerificationLibGoogleTest.inf {
<LibraryClasses>
UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf
UefiBootServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.inf
DxeImageVerificationLib|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibFull.inf
RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
UefiLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.inf
DevicePathLib|MdePkg/Test/Mock/Library/GoogleTest/MockDevicePathLib/MockDevicePathLib.inf
SecurityManagementLib|MdeModulePkg/Test/Mock/Library/GoogleTest/MockSecurityManagementLib/MockSecurityManagementLib.inf
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
}
[PcdsPatchableInModule]
gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x04
gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x04
gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy|0x04