diff options
| author | Alexander Gryanko <xpahos@gmail.com> | 2025-06-22 15:38:43 +0300 |
|---|---|---|
| committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2025-08-07 01:18:26 +0000 |
| commit | 057a611ae6e3c4a1b2811220576a6b48be349cb8 (patch) | |
| tree | 7c5859df9f187291f1f0087c6a5a64173fc59f65 | |
| parent | 5125e2d6b1cd18f73bfed2ad21f29167c64a01e9 (diff) | |
| download | edk2-057a611ae6e3c4a1b2811220576a6b48be349cb8.tar.gz edk2-057a611ae6e3c4a1b2811220576a6b48be349cb8.zip | |
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>
5 files changed, 322 insertions, 0 deletions
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c index 23e25a4b75..5ac6dda5c5 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -1705,6 +1705,13 @@ DxeImageVerificationHandler ( IsFoundInDatabase = FALSE;
//
+ // Sanity check
+ //
+ if (File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
// Check the image type and get policy setting.
//
switch (GetImageType (File)) {
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/GoogleTest/DxeImageVerificationLibGoogleTest.cpp b/SecurityPkg/Library/DxeImageVerificationLib/GoogleTest/DxeImageVerificationLibGoogleTest.cpp new file mode 100644 index 0000000000..325c3f5007 --- /dev/null +++ b/SecurityPkg/Library/DxeImageVerificationLib/GoogleTest/DxeImageVerificationLibGoogleTest.cpp @@ -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 ();
+}
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/GoogleTest/DxeImageVerificationLibGoogleTest.h b/SecurityPkg/Library/DxeImageVerificationLib/GoogleTest/DxeImageVerificationLibGoogleTest.h new file mode 100644 index 0000000000..fcaa0595f4 --- /dev/null +++ b/SecurityPkg/Library/DxeImageVerificationLib/GoogleTest/DxeImageVerificationLibGoogleTest.h @@ -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
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/GoogleTest/DxeImageVerificationLibGoogleTest.inf b/SecurityPkg/Library/DxeImageVerificationLib/GoogleTest/DxeImageVerificationLibGoogleTest.inf new file mode 100644 index 0000000000..78314b57d5 --- /dev/null +++ b/SecurityPkg/Library/DxeImageVerificationLib/GoogleTest/DxeImageVerificationLibGoogleTest.inf @@ -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
diff --git a/SecurityPkg/Test/SecurityPkgHostTest.dsc b/SecurityPkg/Test/SecurityPkgHostTest.dsc index 1655e573ea..7159b20b6b 100644 --- a/SecurityPkg/Test/SecurityPkgHostTest.dsc +++ b/SecurityPkg/Test/SecurityPkgHostTest.dsc @@ -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
|
