mirror of
https://github.com/tianocore/edk2.git
synced 2025-09-16 16:43:03 +00:00
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:
parent
5125e2d6b1
commit
057a611ae6
@ -1704,6 +1704,13 @@ DxeImageVerificationHandler (
|
|||||||
IsFound = FALSE;
|
IsFound = FALSE;
|
||||||
IsFoundInDatabase = FALSE;
|
IsFoundInDatabase = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Sanity check
|
||||||
|
//
|
||||||
|
if (File == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check the image type and get policy setting.
|
// Check the image type and get policy setting.
|
||||||
//
|
//
|
||||||
|
@ -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 ();
|
||||||
|
}
|
@ -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
|
@ -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
|
@ -46,3 +46,23 @@
|
|||||||
PlatformPKProtectionLib|SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf
|
PlatformPKProtectionLib|SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf
|
||||||
UefiLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.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
|
||||||
|
Loading…
Reference in New Issue
Block a user