edk2整体架构
关于安全校验的核心逻辑
Code\Edk2\MdeModulePkg\Universal\SecurityStubDxe\SecurityStub.c
Status = gBS->InstallMultipleProtocolInterfaces (
&mSecurityArchProtocolHandle,
&gEfiSecurity2ArchProtocolGuid,
&mSecurity2Stub,
&gEfiSecurityArchProtocolGuid,
&mSecurityStub,
&gSecurityManagementProtocolGuid,
&mSecurityManagement,
NULL
);
Code\Edk2\MdeModulePkg\Core\PiSmmCore\Dispatcher.c
if (mSecurity2 == NULL) {
gBS->LocateProtocol (&gEfiSecurity2ArchProtocolGuid, NULL, (VOID**)&mSecurity2);
}
if (mSecurity == NULL) {
gBS->LocateProtocol (&gEfiSecurityArchProtocolGuid, NULL, (VOID**)&mSecurity);
}
Code\Edk2\MdeModulePkg\Core\PiSmmCore\Dispatcher.c
SecurityStatus = mSecurity2->FileAuthentication (
mSecurity2,
OriginalFilePath,
Buffer,
Size,
FALSE
);
SecurityStatus = mSecurity->FileAuthenticationState (
mSecurity,
AuthenticationStatus,
OriginalFilePath
);
这三段分别是注册安全句柄,获取安全句柄和使用安全句柄,所有的安全逻辑貌似都是从这里触发的。
再往核心出发就可以看到:
EFI_SECURITY_ARCH_PROTOCOL mSecurityStub = {
SecurityStubAuthenticateState
};
EFI_SECURITY2_ARCH_PROTOCOL mSecurity2Stub = {
Security2StubAuthenticate
};
以及Security2StubAuthenticate的实现:
可以发现stub 又由RegisterSecurity2Handler注册。
这边注册由较多的安全校验函数如下:
DxeImageAuthenticationStatusHandler //未找到调用处
DxeImageVerificationHandler
DxeTpm2MeasureBootHandler
DxeTpmMeasureBootHandler //未找到调用处
DxePlatformImageVerificationHandler //未找到调用处
其中Code\Build\AlderLakeIoTPkg\DEBUG_VS2017\X64\MdeModulePkg\Universal\SecurityStubDxe\SecurityStubDxe\DEBUG\AutoGen.c
VOID
EFIAPI
ProcessLibraryConstructorList (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
......
Status = DxeImageVerificationLibConstructor (ImageHandle, SystemTable);
ASSERT_EFI_ERROR (Status);
Status = DxeTpm2MeasureBootLibConstructor (ImageHandle, SystemTable);
ASSERT_EFI_ERROR (Status);
}
再往上是_ModuleEntryPoint
FileAuthentication
所以结论是FileAuthentication 调用了DxeImageVerificationHandler / DxeTpm2MeasureBootHandler实现了镜像校验。
Status = Tcg2MeasureGptTable (Tcg2Protocol, Handle);
DEBUG ((EFI_D_INFO, "DxeTpm2MeasureBootHandler - Tcg2MeasureGptTable - %r\n", Status));
DbStatus = IsSignatureFoundInDatabase (
EFI_IMAGE_SECURITY_DATABASE1,
mImageDigest,
&mCertType,
mImageDigestSize,
&IsFound
);
if (EFI_ERROR (DbStatus) || IsFound) {
//
// Image Hash is in forbidden database (DBX).
//
DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is forbidden by DBX.\n", mHashTypeStr));
goto Done;
}
调试开关和日志打印
IN CONST EFI_DEVICE_PATH_PROTOCOL *File, OPTIONAL
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode;
OrigDevicePathNode = DuplicateDevicePath (File);
DEBUG_CODE_BEGIN ();
CHAR16 *ToText;
ToText = ConvertDevicePathToText (
DevicePathNode,
FALSE,
TRUE
);
if (ToText != NULL) {
DEBUG ((DEBUG_INFO, "The measured image path is %s.\n", ToText));
FreePool (ToText);
}
DEBUG_CODE_END ();