Add security package to repository.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12261 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
gdong1
2011-09-02 07:49:32 +00:00
parent 986d1dfb08
commit 0c18794ea4
102 changed files with 38487 additions and 0 deletions

View File

@@ -0,0 +1,858 @@
/** @file
Implement defer image load services for user identification in UEFI2.2.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "DxeDeferImageLoadLib.h"
//
// Handle for the Deferred Image Load Protocol instance produced by this driver.
//
EFI_HANDLE mDeferredImageHandle = NULL;
BOOLEAN mIsProtocolInstalled = FALSE;
EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;
DEFERRED_IMAGE_TABLE mDeferredImage = {
0, // Deferred image count
NULL // The deferred image info
};
EFI_DEFERRED_IMAGE_LOAD_PROTOCOL gDeferredImageLoad = {
GetDefferedImageInfo
};
/**
Get the image type.
@param[in] File This is a pointer to the device path of the file
that is being dispatched.
@return UINT32 Image Type
**/
UINT32
GetFileType (
IN CONST EFI_DEVICE_PATH_PROTOCOL *File
)
{
EFI_STATUS Status;
EFI_HANDLE DeviceHandle;
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
//
// First check to see if File is from a Firmware Volume
//
DeviceHandle = NULL;
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
Status = gBS->LocateDevicePath (
&gEfiFirmwareVolume2ProtocolGuid,
&TempDevicePath,
&DeviceHandle
);
if (!EFI_ERROR (Status)) {
Status = gBS->OpenProtocol (
DeviceHandle,
&gEfiFirmwareVolume2ProtocolGuid,
NULL,
NULL,
NULL,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (!EFI_ERROR (Status)) {
return IMAGE_FROM_FV;
}
}
//
// Next check to see if File is from a Block I/O device
//
DeviceHandle = NULL;
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
Status = gBS->LocateDevicePath (
&gEfiBlockIoProtocolGuid,
&TempDevicePath,
&DeviceHandle
);
if (!EFI_ERROR (Status)) {
BlockIo = NULL;
Status = gBS->OpenProtocol (
DeviceHandle,
&gEfiBlockIoProtocolGuid,
(VOID **) &BlockIo,
NULL,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (!EFI_ERROR (Status) && BlockIo != NULL) {
if (BlockIo->Media != NULL) {
if (BlockIo->Media->RemovableMedia) {
//
// Block I/O is present and specifies the media is removable
//
return IMAGE_FROM_REMOVABLE_MEDIA;
} else {
//
// Block I/O is present and specifies the media is not removable
//
return IMAGE_FROM_FIXED_MEDIA;
}
}
}
}
//
// File is not in a Firmware Volume or on a Block I/O device, so check to see if
// the device path supports the Simple File System Protocol.
//
DeviceHandle = NULL;
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
Status = gBS->LocateDevicePath (
&gEfiSimpleFileSystemProtocolGuid,
&TempDevicePath,
&DeviceHandle
);
if (!EFI_ERROR (Status)) {
//
// Simple File System is present without Block I/O, so assume media is fixed.
//
return IMAGE_FROM_FIXED_MEDIA;
}
//
// File is not from an FV, Block I/O or Simple File System, so the only options
// left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC.
//
TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
while (!IsDevicePathEndType (TempDevicePath)) {
switch (DevicePathType (TempDevicePath)) {
case MEDIA_DEVICE_PATH:
if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
return IMAGE_FROM_OPTION_ROM;
}
break;
case MESSAGING_DEVICE_PATH:
if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) {
return IMAGE_FROM_REMOVABLE_MEDIA;
}
break;
default:
break;
}
TempDevicePath = NextDevicePathNode (TempDevicePath);
}
return IMAGE_UNKNOWN;
}
/**
Get current user's access right.
@param[out] AccessControl Points to the user's access control data, the
caller should free data buffer.
@param[in] AccessType The type of user access control.
@retval EFI_SUCCESS Get current user access control successfully
@retval others Fail to get current user access control
**/
EFI_STATUS
GetAccessControl (
OUT EFI_USER_INFO_ACCESS_CONTROL **AccessControl,
IN UINT32 AccessType
)
{
EFI_STATUS Status;
EFI_USER_INFO_HANDLE UserInfo;
EFI_USER_INFO *Info;
UINTN InfoSize;
EFI_USER_INFO_ACCESS_CONTROL *Access;
EFI_USER_PROFILE_HANDLE CurrentUser;
UINTN CheckLen;
EFI_USER_MANAGER_PROTOCOL *UserManager;
CurrentUser = NULL;
Status = gBS->LocateProtocol (
&gEfiUserManagerProtocolGuid,
NULL,
(VOID **) &UserManager
);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
//
// Get current user access information.
//
UserManager->Current (UserManager, &CurrentUser);
UserInfo = NULL;
Info = NULL;
InfoSize = 0;
while (TRUE) {
//
// Get next user information.
//
Status = UserManager->GetNextInfo (UserManager, CurrentUser, &UserInfo);
if (EFI_ERROR (Status)) {
return Status;
}
Status = UserManager->GetInfo (
UserManager,
CurrentUser,
UserInfo,
Info,
&InfoSize
);
if (Status == EFI_BUFFER_TOO_SMALL) {
if (Info != NULL) {
FreePool (Info);
}
Info = AllocateZeroPool (InfoSize);
ASSERT (Info != NULL);
Status = UserManager->GetInfo (
UserManager,
CurrentUser,
UserInfo,
Info,
&InfoSize
);
}
if (EFI_ERROR (Status)) {
break;
}
ASSERT (Info != NULL);
if (Info->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) {
continue;
}
//
// Get specified access information.
//
CheckLen = 0;
while (CheckLen < Info->InfoSize - sizeof (EFI_USER_INFO)) {
Access = (EFI_USER_INFO_ACCESS_CONTROL *) ((UINT8 *) (Info + 1) + CheckLen);
if ((Access->Type == AccessType)) {
*AccessControl = AllocateZeroPool (Access->Size);
ASSERT (*AccessControl != NULL);
CopyMem (*AccessControl, Access, Access->Size);
FreePool (Info);
return EFI_SUCCESS;
}
CheckLen += Access->Size;
}
}
if (Info != NULL) {
FreePool (Info);
}
return EFI_NOT_FOUND;
}
/**
Convert the '/' to '\' in the specified string.
@param[in, out] Str Points to the string to convert.
**/
VOID
ConvertDPStr (
IN OUT EFI_STRING Str
)
{
INTN Count;
INTN Index;
Count = StrSize(Str) / 2 - 1;
if (Count < 4) {
return;
}
//
// Convert device path string.
//
Index = Count - 1;
while (Index > 0) {
//
// Find the last '/'.
//
for (Index = Count - 1; Index > 0; Index--) {
if (Str[Index] == L'/')
break;
}
//
// Check next char.
//
if (Str[Index + 1] == L'\\')
return;
Str[Index] = L'\\';
//
// Check previous char.
//
if ((Index > 0) && (Str[Index - 1] == L'\\')) {
CopyMem (&Str[Index - 1], &Str[Index], (UINTN) ((Count - Index + 1) * sizeof (CHAR16)));
return;
}
Index--;
}
}
/**
Check whether the DevicePath2 is identical with DevicePath1, or identical with
DevicePath1's child device path.
If DevicePath2 is identical with DevicePath1, or with DevicePath1's child device
path, then TRUE returned. Otherwise, FALSE is returned.
If DevicePath1 is NULL, then ASSERT().
If DevicePath2 is NULL, then ASSERT().
@param[in] DevicePath1 A pointer to a device path.
@param[in] DevicePath2 A pointer to a device path.
@retval TRUE Two device paths are identical , or DevicePath2 is
DevicePath1's child device path.
@retval FALSE Two device paths are not identical, and DevicePath2
is not DevicePath1's child device path.
**/
BOOLEAN
CheckDevicePath (
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2
)
{
EFI_STATUS Status;
EFI_STRING DevicePathStr1;
EFI_STRING DevicePathStr2;
UINTN StrLen1;
UINTN StrLen2;
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathText;
BOOLEAN DevicePathEqual;
ASSERT (DevicePath1 != NULL);
ASSERT (DevicePath2 != NULL);
DevicePathEqual = FALSE;
DevicePathText = NULL;
Status = gBS->LocateProtocol (
&gEfiDevicePathToTextProtocolGuid,
NULL,
(VOID **) &DevicePathText
);
ASSERT (Status == EFI_SUCCESS);
//
// Get first device path string.
//
DevicePathStr1 = DevicePathText->ConvertDevicePathToText (DevicePath1, TRUE, TRUE);
ConvertDPStr (DevicePathStr1);
//
// Get second device path string.
//
DevicePathStr2 = DevicePathText->ConvertDevicePathToText (DevicePath2, TRUE, TRUE);
ConvertDPStr (DevicePathStr2);
//
// Compare device path string.
//
StrLen1 = StrSize (DevicePathStr1);
StrLen2 = StrSize (DevicePathStr2);
if (StrLen1 > StrLen2) {
DevicePathEqual = FALSE;
goto Done;
}
if (CompareMem (DevicePathStr1, DevicePathStr2, StrLen1) == 0) {
DevicePathEqual = TRUE;
}
Done:
FreePool (DevicePathStr1);
FreePool (DevicePathStr2);
return DevicePathEqual;
}
/**
Check whether the image pointed to by DevicePath is in the device path list
specified by AccessType.
@param[in] DevicePath Points to device path.
@param[in] AccessType The type of user access control.
@retval TURE The DevicePath is in the specified List.
@retval FALSE The DevicePath is not in the specified List.
**/
BOOLEAN
IsDevicePathInList (
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN UINT32 AccessType
)
{
EFI_STATUS Status;
EFI_USER_INFO_ACCESS_CONTROL *Access;
EFI_DEVICE_PATH_PROTOCOL *Path;
UINTN OffSet;
Status = GetAccessControl (&Access, AccessType);
if (EFI_ERROR (Status)) {
return FALSE;
}
OffSet = 0;
while (OffSet < Access->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {
Path = (EFI_DEVICE_PATH_PROTOCOL*)((UINT8*)(Access + 1) + OffSet);
if (CheckDevicePath (Path, DevicePath)) {
//
// The device path is found in list.
//
FreePool (Access);
return TRUE;
}
OffSet += GetDevicePathSize (Path);
}
FreePool (Access);
return FALSE;
}
/**
Check whether the image pointed to by DevicePath is permitted to load.
@param[in] DevicePath Points to device path
@retval TURE The image pointed by DevicePath is permitted to load.
@retval FALSE The image pointed by DevicePath is forbidden to load.
**/
BOOLEAN
VerifyDevicePath (
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
if (IsDevicePathInList (DevicePath, EFI_USER_INFO_ACCESS_PERMIT_LOAD)) {
//
// This access control overrides any restrictions put in place by the
// EFI_USER_INFO_ACCESS_FORBID_LOAD record.
//
return TRUE;
}
if (IsDevicePathInList (DevicePath, EFI_USER_INFO_ACCESS_FORBID_LOAD)) {
//
// The device path is found in the forbidden list.
//
return FALSE;
}
return TRUE;
}
/**
Check the image pointed by DevicePath is a boot option or not.
@param[in] DevicePath Points to device path.
@retval TURE The image pointed by DevicePath is a boot option.
@retval FALSE The image pointed by DevicePath is not a boot option.
**/
BOOLEAN
IsBootOption (
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
EFI_STATUS Status;
UINT16 *BootOrderList;
UINTN BootOrderListSize;
UINTN Index;
CHAR16 StrTemp[20];
UINT8 *OptionBuffer;
UINT8 *OptionPtr;
EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;
//
// Get BootOrder
//
BootOrderListSize = 0;
BootOrderList = NULL;
Status = gRT->GetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
NULL,
&BootOrderListSize,
NULL
);
if (Status == EFI_BUFFER_TOO_SMALL) {
BootOrderList = AllocateZeroPool (BootOrderListSize);
ASSERT (BootOrderList != NULL);
Status = gRT->GetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
NULL,
&BootOrderListSize,
BootOrderList
);
}
if (EFI_ERROR (Status)) {
//
// No Boot option
//
return FALSE;
}
OptionBuffer = NULL;
for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
//
// Try to find the DevicePath in BootOption
//
UnicodeSPrint (StrTemp, sizeof (StrTemp), L"Boot%04x", Index);
OptionBuffer = GetEfiGlobalVariable (StrTemp);
if (OptionBuffer == NULL) {
continue;
}
//
// Check whether the image is forbidden.
//
OptionPtr = OptionBuffer;
//
// Skip attribute.
//
OptionPtr += sizeof (UINT32);
//
// Skip device path length.
//
OptionPtr += sizeof (UINT16);
//
// Skip descript string
//
OptionPtr += StrSize ((UINT16 *) OptionPtr);
//
// Now OptionPtr points to Device Path.
//
OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) OptionPtr;
if (CheckDevicePath (DevicePath, OptionDevicePath)) {
FreePool (OptionBuffer);
OptionBuffer = NULL;
return TRUE;
}
FreePool (OptionBuffer);
OptionBuffer = NULL;
}
if (BootOrderList != NULL) {
FreePool (BootOrderList);
}
return FALSE;
}
/**
Add the image info to a deferred image list.
@param[in] ImageDevicePath A pointer to the device path of a image.
@param[in] Image Points to the first byte of the image, or NULL if the
image is not available.
@param[in] ImageSize The size of the image, or 0 if the image is not available.
**/
VOID
PutDefferedImageInfo (
IN CONST EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath,
IN VOID *Image,
IN UINTN ImageSize
)
{
DEFERRED_IMAGE_INFO *CurImageInfo;
UINTN PathSize;
//
// Expand memory for the new deferred image.
//
if (mDeferredImage.Count == 0) {
mDeferredImage.ImageInfo = AllocatePool (sizeof (DEFERRED_IMAGE_INFO));
ASSERT (mDeferredImage.ImageInfo != NULL);
} else {
CurImageInfo = AllocatePool ((mDeferredImage.Count + 1) * sizeof (DEFERRED_IMAGE_INFO));
ASSERT (CurImageInfo != NULL);
CopyMem (
CurImageInfo,
mDeferredImage.ImageInfo,
mDeferredImage.Count * sizeof (DEFERRED_IMAGE_INFO)
);
FreePool (mDeferredImage.ImageInfo);
mDeferredImage.ImageInfo = CurImageInfo;
}
mDeferredImage.Count++;
//
// Save the deferred image information.
//
CurImageInfo = &mDeferredImage.ImageInfo[mDeferredImage.Count - 1];
PathSize = GetDevicePathSize (ImageDevicePath);
CurImageInfo->ImageDevicePath = AllocateZeroPool (PathSize);
ASSERT (CurImageInfo->ImageDevicePath != NULL);
CopyMem (CurImageInfo->ImageDevicePath, ImageDevicePath, PathSize);
CurImageInfo->Image = Image;
CurImageInfo->ImageSize = ImageSize;
CurImageInfo->BootOption = IsBootOption (ImageDevicePath);
}
/**
Returns information about a deferred image.
This function returns information about a single deferred image. The deferred images are
numbered consecutively, starting with 0. If there is no image which corresponds to
ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may be returned by
iteratively calling this function until EFI_NOT_FOUND is returned.
Image may be NULL and ImageSize set to 0 if the decision to defer execution was made
because of the location of the executable image, rather than its actual contents.
@param[in] This Points to this instance of the EFI_DEFERRED_IMAGE_LOAD_PROTOCOL.
@param[in] ImageIndex Zero-based index of the deferred index.
@param[out] ImageDevicePath On return, points to a pointer to the device path of the image.
The device path should not be freed by the caller.
@param[out] Image On return, points to the first byte of the image or NULL if the
image is not available. The image should not be freed by the caller
unless LoadImage() has been successfully called.
@param[out] ImageSize On return, the size of the image, or 0 if the image is not available.
@param[out] BootOption On return, points to TRUE if the image was intended as a boot option
or FALSE if it was not intended as a boot option.
@retval EFI_SUCCESS Image information returned successfully.
@retval EFI_NOT_FOUND ImageIndex does not refer to a valid image.
@retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL or ImageSize is NULL or
BootOption is NULL.
**/
EFI_STATUS
EFIAPI
GetDefferedImageInfo (
IN EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *This,
IN UINTN ImageIndex,
OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath,
OUT VOID **Image,
OUT UINTN *ImageSize,
OUT BOOLEAN *BootOption
)
{
DEFERRED_IMAGE_INFO *ReqImageInfo;
//
// Check the parameter.
//
if ((This == NULL) || (ImageSize == NULL) || (Image == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((ImageDevicePath == NULL) || (BootOption == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (ImageIndex >= mDeferredImage.Count) {
return EFI_NOT_FOUND;
}
//
// Get the request deferred image.
//
ReqImageInfo = &mDeferredImage.ImageInfo[ImageIndex];
*ImageDevicePath = ReqImageInfo->ImageDevicePath;
*Image = ReqImageInfo->Image;
*ImageSize = ReqImageInfo->ImageSize;
*BootOption = ReqImageInfo->BootOption;
return EFI_SUCCESS;
}
/**
Provides the service of deferring image load based on platform policy control,
and installs Deferred Image Load Protocol.
@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.
@retval EFI_SUCCESS The file specified by File did authenticate, and the
platform policy dictates that the DXE Core may use File.
@retval EFI_INVALID_PARAMETER File is NULL.
@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. A file may be promoted from
the untrusted to the trusted state at a future time
with a call to the Trust() DXE Service.
@retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
the platform policy dictates that File should not be
used for any purpose.
**/
EFI_STATUS
EFIAPI
DxeDeferImageLoadHandler (
IN UINT32 AuthenticationStatus,
IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
IN VOID *FileBuffer,
IN UINTN FileSize
)
{
EFI_STATUS Status;
EFI_USER_PROFILE_HANDLE CurrentUser;
UINT32 Policy;
UINT32 FileType;
if (File == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Check whether user has a logon.
//
CurrentUser = NULL;
if (mUserManager != NULL) {
mUserManager->Current (mUserManager, &CurrentUser);
if (CurrentUser != NULL) {
//
// The user is logon; verify the FilePath by current user access policy.
//
if (!VerifyDevicePath (File)) {
DEBUG ((EFI_D_ERROR, "[Security] The image is forbidden to load!\n"));
return EFI_ACCESS_DENIED;
}
return EFI_SUCCESS;
}
}
//
// Still no user logon.
// Check the file type and get policy setting.
//
FileType = GetFileType (File);
Policy = PcdGet32 (PcdDeferImageLoadPolicy);
if ((Policy & FileType) == FileType) {
//
// This file type is secure to load.
//
return EFI_SUCCESS;
}
DEBUG ((EFI_D_ERROR, "[Security] No user identified, the image is deferred to load!\n"));
PutDefferedImageInfo (File, NULL, 0);
//
// Install the Deferred Image Load Protocol onto a new handle.
//
if (!mIsProtocolInstalled) {
Status = gBS->InstallMultipleProtocolInterfaces (
&mDeferredImageHandle,
&gEfiDeferredImageLoadProtocolGuid,
&gDeferredImageLoad,
NULL
);
ASSERT_EFI_ERROR (Status);
mIsProtocolInstalled = TRUE;
}
return EFI_ACCESS_DENIED;
}
/**
Locate user manager protocol when user manager is installed.
@param[in] Event The Event that is being processed, not used.
@param[in] Context Event Context, not used.
**/
VOID
EFIAPI
FindUserManagerProtocol (
IN EFI_EVENT Event,
IN VOID* Context
)
{
gBS->LocateProtocol (
&gEfiUserManagerProtocolGuid,
NULL,
(VOID **) &mUserManager
);
}
/**
Register security handler for deferred image load.
@param[in] ImageHandle ImageHandle of the loaded driver.
@param[in] SystemTable Pointer to the EFI System Table.
@retval EFI_SUCCESS The handlers were registered successfully.
**/
EFI_STATUS
EFIAPI
DxeDeferImageLoadLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
VOID *Registration;
//
// Register user manager notification function.
//
EfiCreateProtocolNotifyEvent (
&gEfiUserManagerProtocolGuid,
TPL_CALLBACK,
FindUserManagerProtocol,
NULL,
&Registration
);
return RegisterSecurityHandler (
DxeDeferImageLoadHandler,
EFI_AUTH_OPERATION_DEFER_IMAGE_LOAD
);
}

View File

@@ -0,0 +1,106 @@
/** @file
The internal header file includes the common header files, defines
internal structure and functions used by DeferImageLoadLib.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __DEFER_IMAGE_LOAD_LIB_H__
#define __DEFER_IMAGE_LOAD_LIB_H__
#include <PiDxe.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/SecurityManagementLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DevicePathLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/PrintLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Library/PcdLib.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/BlockIo.h>
#include <Protocol/SimpleFileSystem.h>
#include <Protocol/DeferredImageLoad.h>
#include <Protocol/UserCredential.h>
#include <Protocol/UserManager.h>
#include <Protocol/DevicePathToText.h>
#include <Guid/GlobalVariable.h>
//
// Image type definitions.
//
#define IMAGE_UNKNOWN 0x00000001
#define IMAGE_FROM_FV 0x00000002
#define IMAGE_FROM_OPTION_ROM 0x00000004
#define IMAGE_FROM_REMOVABLE_MEDIA 0x00000008
#define IMAGE_FROM_FIXED_MEDIA 0x00000010
//
// The struct to save the deferred image information.
//
typedef struct {
EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
VOID *Image;
UINTN ImageSize;
BOOLEAN BootOption;
} DEFERRED_IMAGE_INFO;
//
// The table to save the deferred image item.
//
typedef struct {
UINTN Count; ///< deferred image count
DEFERRED_IMAGE_INFO *ImageInfo; ///< deferred image item
} DEFERRED_IMAGE_TABLE;
/**
Returns information about a deferred image.
This function returns information about a single deferred image. The deferred images are
numbered consecutively, starting with 0. If there is no image which corresponds to
ImageIndex, then EFI_NOT_FOUND is returned. All deferred images may be returned by
iteratively calling this function until EFI_NOT_FOUND is returned.
Image may be NULL and ImageSize set to 0 if the decision to defer execution was made
because of the location of the executable image, rather than its actual contents.
@param[in] This Points to this instance of the EFI_DEFERRED_IMAGE_LOAD_PROTOCOL.
@param[in] ImageIndex Zero-based index of the deferred index.
@param[out] ImageDevicePath On return, points to a pointer to the device path of the image.
The device path should not be freed by the caller.
@param[out] Image On return, points to the first byte of the image or NULL if the
image is not available. The image should not be freed by the caller
unless LoadImage() has been called successfully.
@param[out] ImageSize On return, the size of the image, or 0 if the image is not available.
@param[out] BootOption On return, points to TRUE if the image was intended as a boot option
or FALSE if it was not intended as a boot option.
@retval EFI_SUCCESS Image information returned successfully.
@retval EFI_NOT_FOUND ImageIndex does not refer to a valid image.
@retval EFI_INVALID_PARAMETER ImageDevicePath is NULL or Image is NULL or ImageSize is NULL or
BootOption is NULL.
**/
EFI_STATUS
EFIAPI
GetDefferedImageInfo (
IN EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *This,
IN UINTN ImageIndex,
OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath,
OUT VOID **Image,
OUT UINTN *ImageSize,
OUT BOOLEAN *BootOption
);
#endif

View File

@@ -0,0 +1,62 @@
## @file
# The library instance provides security service of deferring image load.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = DxeDeferImageLoadLib
FILE_GUID = 5E2FAE1F-41DA-4fbd-BC81-603CE5CD8497
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = NULL|DXE_DRIVER UEFI_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION
CONSTRUCTOR = DxeDeferImageLoadLibConstructor
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 EBC
#
[Sources]
DxeDeferImageLoadLib.c
DxeDeferImageLoadLib.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
SecurityPkg/SecurityPkg.dec
[LibraryClasses]
UefiRuntimeServicesTableLib
UefiBootServicesTableLib
SecurityManagementLib
MemoryAllocationLib
DevicePathLib
BaseMemoryLib
PrintLib
DebugLib
UefiLib
PcdLib
[Protocols]
gEfiFirmwareVolume2ProtocolGuid
gEfiBlockIoProtocolGuid
gEfiSimpleFileSystemProtocolGuid
gEfiUserManagerProtocolGuid
gEfiDeferredImageLoadProtocolGuid
gEfiDevicePathToTextProtocolGuid
[Guids]
gEfiGlobalVariableGuid
[Pcd]
gEfiSecurityPkgTokenSpaceGuid.PcdDeferImageLoadPolicy

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,201 @@
/** @file
The internal header file includes the common header files, defines
internal structure and functions used by ImageVerificationLib.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __IMAGEVERIFICATIONLIB_H__
#define __IMAGEVERIFICATIONLIB_H__
#include <Library/UefiDriverEntryPoint.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseCryptLib.h>
#include <Library/PcdLib.h>
#include <Library/DevicePathLib.h>
#include <Library/SecurityManagementLib.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/DevicePath.h>
#include <Protocol/BlockIo.h>
#include <Protocol/SimpleFileSystem.h>
#include <Protocol/VariableWrite.h>
#include <Guid/ImageAuthentication.h>
#include <IndustryStandard/PeImage.h>
#define EFI_CERT_TYPE_RSA2048_SHA256_SIZE 256
#define EFI_CERT_TYPE_RSA2048_SIZE 256
#define MAX_NOTIFY_STRING_LEN 64
//
// Image type definitions
//
#define IMAGE_UNKNOWN 0x00000000
#define IMAGE_FROM_FV 0x00000001
#define IMAGE_FROM_OPTION_ROM 0x00000002
#define IMAGE_FROM_REMOVABLE_MEDIA 0x00000003
#define IMAGE_FROM_FIXED_MEDIA 0x00000004
//
// Authorization policy bit definition
//
#define ALWAYS_EXECUTE 0x00000000
#define NEVER_EXECUTE 0x00000001
#define ALLOW_EXECUTE_ON_SECURITY_VIOLATION 0x00000002
#define DEFER_EXECUTE_ON_SECURITY_VIOLATION 0x00000003
#define DENY_EXECUTE_ON_SECURITY_VIOLATION 0x00000004
#define QUERY_USER_ON_SECURITY_VIOLATION 0x00000005
//
// Support hash types
//
#define HASHALG_SHA1 0x00000000
#define HASHALG_SHA224 0x00000001
#define HASHALG_SHA256 0x00000002
#define HASHALG_SHA384 0x00000003
#define HASHALG_SHA512 0x00000004
#define HASHALG_MAX 0x00000005
//
// Set max digest size as SHA256 Output (32 bytes) by far
//
#define MAX_DIGEST_SIZE SHA256_DIGEST_SIZE
//
//
// PKCS7 Certificate definition
//
typedef struct {
WIN_CERTIFICATE Hdr;
UINT8 CertData[1];
} WIN_CERTIFICATE_EFI_PKCS;
/**
Retrieves the size, in bytes, of the context buffer required for hash operations.
@return The size, in bytes, of the context buffer required for hash operations.
**/
typedef
UINTN
(EFIAPI *HASH_GET_CONTEXT_SIZE)(
VOID
);
/**
Initializes user-supplied memory pointed by HashContext as hash context for
subsequent use.
If HashContext is NULL, then ASSERT().
@param[in, out] HashContext Pointer to Context being initialized.
@retval TRUE HASH context initialization succeeded.
@retval FALSE HASH context initialization failed.
**/
typedef
BOOLEAN
(EFIAPI *HASH_INIT)(
IN OUT VOID *HashContext
);
/**
Performs digest on a data buffer of the specified length. This function can
be called multiple times to compute the digest of long or discontinuous data streams.
If HashContext is NULL, then ASSERT().
@param[in, out] HashContext Pointer to the MD5 context.
@param[in] Data Pointer to the buffer containing the data to be hashed.
@param[in] DataLength Length of Data buffer in bytes.
@retval TRUE HASH data digest succeeded.
@retval FALSE Invalid HASH context. After HashFinal function has been called, the
HASH context cannot be reused.
**/
typedef
BOOLEAN
(EFIAPI *HASH_UPDATE)(
IN OUT VOID *HashContext,
IN CONST VOID *Data,
IN UINTN DataLength
);
/**
Completes hash computation and retrieves the digest value into the specified
memory. After this function has been called, the context cannot be used again.
If HashContext is NULL, then ASSERT().
If HashValue is NULL, then ASSERT().
@param[in, out] HashContext Pointer to the MD5 context
@param[out] HashValue Pointer to a buffer that receives the HASH digest
value.
@retval TRUE HASH digest computation succeeded.
@retval FALSE HASH digest computation failed.
**/
typedef
BOOLEAN
(EFIAPI *HASH_FINAL)(
IN OUT VOID *HashContext,
OUT UINT8 *HashValue
);
//
// Hash Algorithm Table
//
typedef struct {
//
// Name for Hash Algorithm
//
CHAR16 *Name;
//
// Digest Length
//
UINTN DigestLength;
//
// Hash Algorithm OID ASN.1 Value
//
UINT8 *OidValue;
//
// Length of Hash OID Value
//
UINTN OidLength;
//
// Pointer to Hash GetContentSize function
//
HASH_GET_CONTEXT_SIZE GetContextSize;
//
// Pointer to Hash Init function
//
HASH_INIT HashInit;
//
// Pointer to Hash Update function
//
HASH_UPDATE HashUpdate;
//
// Pointer to Hash Final function
//
HASH_FINAL HashFinal;
} HASH_TABLE;
#endif

View File

@@ -0,0 +1,73 @@
## @file
# The library instance provides security service of image verification.
# Image verification Library module supports UEFI2.3.1
#
# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = DxeImageVerificationLib
FILE_GUID = 0CA970E1-43FA-4402-BC0A-81AF336BFFD6
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = NULL|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
CONSTRUCTOR = DxeImageVerificationLibConstructor
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
DxeImageVerificationLib.c
DxeImageVerificationLib.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
CryptoPkg/CryptoPkg.dec
SecurityPkg/SecurityPkg.dec
[LibraryClasses]
MemoryAllocationLib
BaseLib
UefiLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
BaseMemoryLib
DebugLib
DevicePathLib
BaseCryptLib
SecurityManagementLib
[Protocols]
gEfiFirmwareVolume2ProtocolGuid
gEfiBlockIoProtocolGuid
gEfiSimpleFileSystemProtocolGuid
gEfiVariableWriteArchProtocolGuid
[Guids]
gEfiCertTypeRsa2048Sha256Guid
gEfiImageSecurityDatabaseGuid
gEfiCertSha1Guid
gEfiCertSha256Guid
gEfiCertX509Guid
gEfiCertRsa2048Guid
[Pcd]
gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy
gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy
gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy

View File

@@ -0,0 +1,830 @@
/** @file
The library instance provides security service of TPM measure boot.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <PiDxe.h>
#include <Protocol/TcgService.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/BlockIo.h>
#include <Protocol/DiskIo.h>
#include <Protocol/DevicePathToText.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DevicePathLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseCryptLib.h>
#include <Library/PeCoffLib.h>
#include <Library/SecurityManagementLib.h>
//
// Flag to check GPT partition. It only need be measured once.
//
BOOLEAN mMeasureGptTableFlag = FALSE;
EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
UINTN mMeasureGptCount = 0;
/**
Reads contents of a PE/COFF image in memory buffer.
@param FileHandle Pointer to the file handle to read the PE/COFF image.
@param FileOffset Offset into the PE/COFF image to begin the read operation.
@param ReadSize On input, the size in bytes of the requested read operation.
On output, the number of bytes actually read.
@param Buffer Output buffer that contains the data read from the PE/COFF image.
@retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size
**/
EFI_STATUS
EFIAPI
ImageRead (
IN VOID *FileHandle,
IN UINTN FileOffset,
IN OUT UINTN *ReadSize,
OUT VOID *Buffer
)
{
CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);
return EFI_SUCCESS;
}
/**
Measure GPT table data into TPM log.
@param TcgProtocol Pointer to the located TCG protocol instance.
@param GptHandle Handle that GPT partition was installed.
@retval EFI_SUCCESS Successfully measure GPT table.
@retval EFI_UNSUPPORTED Not support GPT table on the given handle.
@retval EFI_DEVICE_ERROR Can't get GPT table because device error.
@retval EFI_OUT_OF_RESOURCES No enough resource to measure GPT table.
@retval other error value
**/
EFI_STATUS
EFIAPI
TcgMeasureGptTable (
IN EFI_TCG_PROTOCOL *TcgProtocol,
IN EFI_HANDLE GptHandle
)
{
EFI_STATUS Status;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
EFI_DISK_IO_PROTOCOL *DiskIo;
EFI_PARTITION_TABLE_HEADER *PrimaryHeader;
EFI_PARTITION_ENTRY *PartitionEntry;
UINT8 *EntryPtr;
UINTN NumberOfPartition;
UINT32 Index;
TCG_PCR_EVENT *TcgEvent;
EFI_GPT_DATA *GptData;
UINT32 EventSize;
UINT32 EventNumber;
EFI_PHYSICAL_ADDRESS EventLogLastEntry;
if (mMeasureGptCount > 0) {
return EFI_SUCCESS;
}
Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID**)&DiskIo);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
//
// Read the EFI Partition Table Header
//
PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *) AllocatePool (BlockIo->Media->BlockSize);
if (PrimaryHeader == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = DiskIo->ReadDisk (
DiskIo,
BlockIo->Media->MediaId,
1 * BlockIo->Media->BlockSize,
BlockIo->Media->BlockSize,
(UINT8 *)PrimaryHeader
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Failed to Read Partition Table Header!\n"));
FreePool (PrimaryHeader);
return EFI_DEVICE_ERROR;
}
//
// Read the partition entry.
//
EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);
if (EntryPtr == NULL) {
FreePool (PrimaryHeader);
return EFI_OUT_OF_RESOURCES;
}
Status = DiskIo->ReadDisk (
DiskIo,
BlockIo->Media->MediaId,
MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,
EntryPtr
);
if (EFI_ERROR (Status)) {
FreePool (PrimaryHeader);
FreePool (EntryPtr);
return EFI_DEVICE_ERROR;
}
//
// Count the valid partition
//
PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr;
NumberOfPartition = 0;
for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) {
NumberOfPartition++;
}
PartitionEntry++;
}
//
// Parepare Data for Measurement
//
EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions)
+ NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);
TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));
if (TcgEvent == NULL) {
FreePool (PrimaryHeader);
FreePool (EntryPtr);
return EFI_OUT_OF_RESOURCES;
}
TcgEvent->PCRIndex = 5;
TcgEvent->EventType = EV_EFI_GPT_EVENT;
TcgEvent->EventSize = EventSize;
GptData = (EFI_GPT_DATA *) TcgEvent->Event;
//
// Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition
//
CopyMem ((UINT8 *)GptData, (UINT8*)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER));
GptData->NumberOfPartitions = NumberOfPartition;
//
// Copy the valid partition entry
//
PartitionEntry = (EFI_PARTITION_ENTRY*)EntryPtr;
NumberOfPartition = 0;
for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) {
CopyMem (
(UINT8 *)&GptData->Partitions + NumberOfPartition * sizeof (EFI_PARTITION_ENTRY),
(UINT8 *)PartitionEntry,
sizeof (EFI_PARTITION_ENTRY)
);
NumberOfPartition++;
}
PartitionEntry++;
}
//
// Measure the GPT data
//
EventNumber = 1;
Status = TcgProtocol->HashLogExtendEvent (
TcgProtocol,
(EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) GptData,
(UINT64) TcgEvent->EventSize,
TPM_ALG_SHA,
TcgEvent,
&EventNumber,
&EventLogLastEntry
);
if (!EFI_ERROR (Status)) {
mMeasureGptCount++;
}
FreePool (PrimaryHeader);
FreePool (EntryPtr);
FreePool (TcgEvent);
return Status;
}
/**
Measure PE image into TPM log based on the authenticode image hashing in
PE/COFF Specification 8.0 Appendix A.
@param[in] TcgProtocol Pointer to the located TCG protocol instance.
@param[in] ImageAddress Start address of image buffer.
@param[in] ImageSize Image size
@param[in] LinkTimeBase Address that the image is loaded into memory.
@param[in] ImageType Image subsystem type.
@param[in] FilePath File path is corresponding to the input image.
@retval EFI_SUCCESS Successfully measure image.
@retval EFI_OUT_OF_RESOURCES No enough resource to measure image.
@retval other error value
**/
EFI_STATUS
EFIAPI
TcgMeasurePeImage (
IN EFI_TCG_PROTOCOL *TcgProtocol,
IN EFI_PHYSICAL_ADDRESS ImageAddress,
IN UINTN ImageSize,
IN UINTN LinkTimeBase,
IN UINT16 ImageType,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
)
{
EFI_STATUS Status;
TCG_PCR_EVENT *TcgEvent;
EFI_IMAGE_LOAD_EVENT *ImageLoad;
UINT32 FilePathSize;
VOID *Sha1Ctx;
UINTN CtxSize;
EFI_IMAGE_DOS_HEADER *DosHdr;
UINT32 PeCoffHeaderOffset;
EFI_IMAGE_SECTION_HEADER *Section;
UINT8 *HashBase;
UINTN HashSize;
UINTN SumOfBytesHashed;
EFI_IMAGE_SECTION_HEADER *SectionHeader;
UINTN Index, Pos;
UINT16 Magic;
UINT32 EventSize;
UINT32 EventNumber;
EFI_PHYSICAL_ADDRESS EventLogLastEntry;
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
Status = EFI_SUCCESS;
ImageLoad = NULL;
SectionHeader = NULL;
Sha1Ctx = NULL;
FilePathSize = (UINT32) GetDevicePathSize (FilePath);
//
// Determine destination PCR by BootPolicy
//
EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
TcgEvent = AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));
if (TcgEvent == NULL) {
return EFI_OUT_OF_RESOURCES;
}
TcgEvent->EventSize = EventSize;
ImageLoad = (EFI_IMAGE_LOAD_EVENT *) TcgEvent->Event;
switch (ImageType) {
case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
TcgEvent->EventType = EV_EFI_BOOT_SERVICES_APPLICATION;
TcgEvent->PCRIndex = 4;
break;
case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
TcgEvent->EventType = EV_EFI_BOOT_SERVICES_DRIVER;
TcgEvent->PCRIndex = 2;
break;
case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
TcgEvent->EventType = EV_EFI_RUNTIME_SERVICES_DRIVER;
TcgEvent->PCRIndex = 2;
break;
default:
DEBUG ((
EFI_D_ERROR,
"TcgMeasurePeImage: Unknown subsystem type %d",
ImageType
));
ASSERT (FALSE);
TcgEvent->EventType = ImageType;
Status = EFI_UNSUPPORTED;
goto Finish;
}
ImageLoad->ImageLocationInMemory = ImageAddress;
ImageLoad->ImageLengthInMemory = ImageSize;
ImageLoad->ImageLinkTimeAddress = LinkTimeBase;
ImageLoad->LengthOfDevicePath = FilePathSize;
CopyMem (ImageLoad->DevicePath, FilePath, FilePathSize);
//
// Check PE/COFF image
//
DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress;
PeCoffHeaderOffset = 0;
if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
PeCoffHeaderOffset = DosHdr->e_lfanew;
}
if (((EFI_TE_IMAGE_HEADER *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset))->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE) {
goto Finish;
}
//
// PE/COFF Image Measurement
//
// NOTE: The following codes/steps are based upon the authenticode image hashing in
// PE/COFF Specification 8.0 Appendix A.
//
//
// 1. Load the image header into memory.
// 2. Initialize a SHA hash context.
CtxSize = Sha1GetContextSize ();
Sha1Ctx = AllocatePool (CtxSize);
if (Sha1Ctx == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Finish;
}
Sha1Init (Sha1Ctx);
//
// Measuring PE/COFF Image Header;
// But CheckSum field and SECURITY data directory (certificate) are excluded
//
Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);
Magic = Hdr.Pe32->OptionalHeader.Magic;
//
// 3. Calculate the distance from the base of the image header to the image checksum address.
// 4. Hash the image header from its base to beginning of the image checksum.
//
HashBase = (UINT8 *) (UINTN) ImageAddress;
if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
//
// Use PE32 offset
//
HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.CheckSum) - HashBase);
} else {
//
// Use PE32+ offset
//
HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - HashBase);
}
Sha1Update (Sha1Ctx, HashBase, HashSize);
//
// 5. Skip over the image checksum (it occupies a single ULONG).
// 6. Get the address of the beginning of the Cert Directory.
// 7. Hash everything from the end of the checksum to the start of the Cert Directory.
//
if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
//
// Use PE32 offset
//
HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
} else {
//
// Use PE32+ offset
//
HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
}
Sha1Update (Sha1Ctx, HashBase, HashSize);
//
// 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
// 9. Hash everything from the end of the Cert Directory to the end of image header.
//
if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
//
// Use PE32 offset
//
HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders -
(UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) (UINTN) ImageAddress);
} else {
//
// Use PE32+ offset
//
HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders -
(UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) (UINTN) ImageAddress);
}
Sha1Update (Sha1Ctx, HashBase, HashSize);
//
// 10. Set the SUM_OF_BYTES_HASHED to the size of the header
//
if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
//
// Use PE32 offset
//
SumOfBytesHashed = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
} else {
//
// Use PE32+ offset
//
SumOfBytesHashed = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders;
}
//
// 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
// structures in the image. The 'NumberOfSections' field of the image
// header indicates how big the table should be. Do not include any
// IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
//
SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections);
if (SectionHeader == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Finish;
}
//
// 12. Using the 'PointerToRawData' in the referenced section headers as
// a key, arrange the elements in the table in ascending order. In other
// words, sort the section headers according to the disk-file offset of
// the section.
//
Section = (EFI_IMAGE_SECTION_HEADER *) (
(UINT8 *) (UINTN) ImageAddress +
PeCoffHeaderOffset +
sizeof(UINT32) +
sizeof(EFI_IMAGE_FILE_HEADER) +
Hdr.Pe32->FileHeader.SizeOfOptionalHeader
);
for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
Pos = Index;
while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {
CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof(EFI_IMAGE_SECTION_HEADER));
Pos--;
}
CopyMem (&SectionHeader[Pos], Section, sizeof(EFI_IMAGE_SECTION_HEADER));
Section += 1;
}
//
// 13. Walk through the sorted table, bring the corresponding section
// into memory, and hash the entire section (using the 'SizeOfRawData'
// field in the section header to determine the amount of data to hash).
// 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
// 15. Repeat steps 13 and 14 for all the sections in the sorted table.
//
for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
Section = (EFI_IMAGE_SECTION_HEADER *) &SectionHeader[Index];
if (Section->SizeOfRawData == 0) {
continue;
}
HashBase = (UINT8 *) (UINTN) ImageAddress + Section->PointerToRawData;
HashSize = (UINTN) Section->SizeOfRawData;
Sha1Update (Sha1Ctx, HashBase, HashSize);
SumOfBytesHashed += HashSize;
}
//
// 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
// data in the file that needs to be added to the hash. This data begins
// at file offset SUM_OF_BYTES_HASHED and its length is:
// FileSize - (CertDirectory->Size)
//
if (ImageSize > SumOfBytesHashed) {
HashBase = (UINT8 *) (UINTN) ImageAddress + SumOfBytesHashed;
if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
//
// Use PE32 offset
//
HashSize = (UINTN)(ImageSize -
Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
SumOfBytesHashed);
} else {
//
// Use PE32+ offset
//
HashSize = (UINTN)(ImageSize -
Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -
SumOfBytesHashed);
}
Sha1Update (Sha1Ctx, HashBase, HashSize);
}
//
// 17. Finalize the SHA hash.
//
Sha1Final (Sha1Ctx, (UINT8 *)&TcgEvent->Digest);
//
// Log the PE data
//
EventNumber = 1;
Status = TcgProtocol->HashLogExtendEvent (
TcgProtocol,
(EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) NULL,
0,
TPM_ALG_SHA,
TcgEvent,
&EventNumber,
&EventLogLastEntry
);
Finish:
FreePool (TcgEvent);
if (SectionHeader != NULL) {
FreePool (SectionHeader);
}
if (Sha1Ctx != NULL ) {
FreePool (Sha1Ctx);
}
return Status;
}
/**
The security handler is used to abstract platform-specific policy
from the DXE core response to an attempt to use a file that returns a
given status for the authentication check from the section extraction protocol.
The possible responses in a given SAP implementation may include locking
flash upon failure to authenticate, attestation logging for all signed drivers,
and other exception operations. The File parameter allows for possible logging
within the SAP of the driver.
If File is NULL, then EFI_INVALID_PARAMETER is returned.
If the file specified by File with an authentication status specified by
AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned.
If the file specified by File with an authentication status specified by
AuthenticationStatus is not safe for the DXE Core to use under any circumstances,
then EFI_ACCESS_DENIED is returned.
If the file specified by File with an authentication status specified by
AuthenticationStatus is not safe for the DXE Core to use right now, but it
might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is
returned.
@param[in, out] AuthenticationStatus This is the authentication status returned
from the securitymeasurement 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.
@retval EFI_SUCCESS The file specified by File did authenticate, and the
platform policy dictates that the DXE Core may use File.
@retval EFI_INVALID_PARAMETER File is NULL.
@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. A file may be promoted from
the untrusted to the trusted state at a future time
with a call to the Trust() DXE Service.
@retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and
the platform policy dictates that File should not be
used for any purpose.
**/
EFI_STATUS
EFIAPI
DxeTpmMeasureBootHandler (
IN OUT UINT32 AuthenticationStatus,
IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
IN VOID *FileBuffer OPTIONAL,
IN UINTN FileSize OPTIONAL
)
{
EFI_TCG_PROTOCOL *TcgProtocol;
EFI_STATUS Status;
TCG_EFI_BOOT_SERVICE_CAPABILITY ProtocolCapability;
UINT32 TCGFeatureFlags;
EFI_PHYSICAL_ADDRESS EventLogLocation;
EFI_PHYSICAL_ADDRESS EventLogLastEntry;
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode;
EFI_HANDLE Handle;
BOOLEAN ApplicationRequired;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
if (File == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &TcgProtocol);
if (EFI_ERROR (Status)) {
//
// TCG protocol is not installed. So, TPM is not present.
// Don't do any measurement, and directly return EFI_SUCCESS.
//
return EFI_SUCCESS;
}
ProtocolCapability.Size = (UINT8) sizeof (ProtocolCapability);
Status = TcgProtocol->StatusCheck (
TcgProtocol,
&ProtocolCapability,
&TCGFeatureFlags,
&EventLogLocation,
&EventLogLastEntry
);
if (EFI_ERROR (Status) || ProtocolCapability.TPMDeactivatedFlag) {
//
// TPM device doesn't work or activate.
//
return EFI_SUCCESS;
}
//
// Copy File Device Path
//
OrigDevicePathNode = DuplicateDevicePath (File);
ASSERT (OrigDevicePathNode != NULL);
//
// 1. Check whether this device path support BlockIo protocol.
// Is so, this device path may be a GPT device path.
//
DevicePathNode = OrigDevicePathNode;
Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePathNode, &Handle);
if (!EFI_ERROR (Status) && !mMeasureGptTableFlag) {
//
// Find the gpt partion on the given devicepath
//
DevicePathNode = OrigDevicePathNode;
while (!IsDevicePathEnd (DevicePathNode)) {
//
// Find the Gpt partition
//
if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH &&
DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP) {
//
// Check whether it is a gpt partition or not
//
if (((HARDDRIVE_DEVICE_PATH *) DevicePathNode)->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER &&
((HARDDRIVE_DEVICE_PATH *) DevicePathNode)->SignatureType == SIGNATURE_TYPE_GUID) {
//
// Change the partition device path to its parent device path (disk) and get the handle.
//
DevicePathNode->Type = END_DEVICE_PATH_TYPE;
DevicePathNode->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
DevicePathNode = OrigDevicePathNode;
Status = gBS->LocateDevicePath (
&gEfiDiskIoProtocolGuid,
&DevicePathNode,
&Handle
);
if (!EFI_ERROR (Status)) {
//
// Measure GPT disk.
//
Status = TcgMeasureGptTable (TcgProtocol, Handle);
if (!EFI_ERROR (Status)) {
//
// GPT disk check done.
//
mMeasureGptTableFlag = TRUE;
}
}
FreePool (OrigDevicePathNode);
OrigDevicePathNode = DuplicateDevicePath (File);
ASSERT (OrigDevicePathNode != NULL);
break;
}
}
DevicePathNode = NextDevicePathNode (DevicePathNode);
}
}
//
// 2. Measure PE image.
//
ApplicationRequired = FALSE;
//
// Check whether this device path support FV2 protocol.
//
DevicePathNode = OrigDevicePathNode;
Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePathNode, &Handle);
if (!EFI_ERROR (Status)) {
//
// Don't check FV image, and directly return EFI_SUCCESS.
// It can be extended to the specific FV authentication according to the different requirement.
//
if (IsDevicePathEnd (DevicePathNode)) {
return EFI_SUCCESS;
}
//
// The image from Firmware image will not be mearsured.
// Current policy doesn't measure PeImage from Firmware if it is driver
// If the got PeImage is application, it will be still be measured.
//
ApplicationRequired = TRUE;
}
//
// File is not found.
//
if (FileBuffer == NULL) {
Status = EFI_SECURITY_VIOLATION;
goto Finish;
}
//
// Measure PE Image
//
DevicePathNode = OrigDevicePathNode;
ZeroMem (&ImageContext, sizeof (ImageContext));
ImageContext.Handle = (VOID *) FileBuffer;
ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) ImageRead;
//
// Get information about the image being loaded
//
Status = PeCoffLoaderGetImageInfo (&ImageContext);
if (EFI_ERROR (Status)) {
//
// The information can't be got from the invalid PeImage
//
goto Finish;
}
//
// Measure only application if Application flag is set
// Measure drivers and applications if Application flag is not set
//
if ((!ApplicationRequired) ||
(ApplicationRequired && ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION)) {
//
// Print the image path to be measured.
//
DEBUG_CODE_BEGIN ();
CHAR16 *ToText;
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
Status = gBS->LocateProtocol (
&gEfiDevicePathToTextProtocolGuid,
NULL,
(VOID **) &DevPathToText
);
if (!EFI_ERROR (Status)) {
ToText = DevPathToText->ConvertDevicePathToText (
DevicePathNode,
FALSE,
TRUE
);
if (ToText != NULL) {
DEBUG ((DEBUG_INFO, "The measured image path is %s.\n", ToText));
}
}
DEBUG_CODE_END ();
//
// Measure PE image into TPM log.
//
Status = TcgMeasurePeImage (
TcgProtocol,
(EFI_PHYSICAL_ADDRESS) (UINTN) FileBuffer,
FileSize,
(UINTN) ImageContext.ImageAddress,
ImageContext.ImageType,
DevicePathNode
);
}
//
// Done, free the allocated resource.
//
Finish:
FreePool (OrigDevicePathNode);
return Status;
}
/**
Register the security handler to provide TPM measure boot service.
@param ImageHandle ImageHandle of the loaded driver.
@param SystemTable Pointer to the EFI System Table.
@retval EFI_SUCCESS Register successfully.
@retval EFI_OUT_OF_RESOURCES No enough memory to register this handler.
**/
EFI_STATUS
EFIAPI
DxeTpmMeasureBootLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return RegisterSecurityHandler (
DxeTpmMeasureBootHandler,
EFI_AUTH_OPERATION_MEASURE_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED
);
}

View File

@@ -0,0 +1,54 @@
## @file
# The library instance provides security service of TPM measure boot.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = DxeTpmMeasureBootLib
FILE_GUID = 6C60C7D0-922A-4b7c-87D7-E503EDD73BBF
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = NULL|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
CONSTRUCTOR = DxeTpmMeasureBootLibConstructor
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
DxeTpmMeasureBootLib.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
BaseMemoryLib
DebugLib
MemoryAllocationLib
DevicePathLib
UefiBootServicesTableLib
BaseCryptLib
PeCoffLib
BaseLib
SecurityManagementLib
[Protocols]
gEfiTcgProtocolGuid ## CONSUMES
gEfiFirmwareVolume2ProtocolGuid ## CONSUMES
gEfiBlockIoProtocolGuid ## CONSUMES
gEfiDiskIoProtocolGuid ## CONSUMES
gEfiDevicePathToTextProtocolGuid ## SOMETIMES_CONSUMES (Only used in debug mode)

View File

@@ -0,0 +1,39 @@
/** @file
Provides a secure platform-specific method to clear PK(Platform Key).
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
/**
This function detects whether a secure platform-specific method to clear PK(Platform Key)
is configured by platform owner. This method is provided for users force to clear PK
in case incorrect enrollment mis-haps.
UEFI231 spec chapter 27.5.2 stipulates: The platform key may also be cleared using
a secure platform-specific method. In this case, the global variable SetupMode
must also be updated to 1.
NOTE THAT: This function cannot depend on any EFI Variable Service since they are
not available when this function is called in AuthenticateVariable driver.
@retval TRUE The Platform owner wants to force clear PK.
@retval FALSE The Platform owner doesn't want to force clear PK.
**/
BOOLEAN
EFIAPI
ForceClearPK (
VOID
)
{
return FALSE;
}

View File

@@ -0,0 +1,33 @@
## @file
# Provides a secure platform-specific method to clear PK(Platform Key).
#
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PlatformSecureLibNull
FILE_GUID = 7FA68D82-10A4-4e71-9524-D3D9500D3CDF
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = PlatformSecureLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
PlatformSecureLibNull.c
[Packages]
MdePkg/MdePkg.dec

View File

@@ -0,0 +1,29 @@
/** @file
The intenal header file for TpmCommLib.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _TPMCOMMLIB_COMMON_HEADER_H_
#define _TPMCOMMLIB_COMMON_HEADER_H_
#include <PiPei.h>
#include <IndustryStandard/Tpm12.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/IoLib.h>
#include <Library/TimerLib.h>
#include <Library/TpmCommLib.h>
#include <Library/BaseCryptLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#endif

View File

@@ -0,0 +1,180 @@
/** @file
Basic TIS (TPM Interface Specification) functions.
Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "CommonHeader.h"
/**
Check whether TPM chip exist.
@param[in] TisReg Pointer to TIS register.
@retval TRUE TPM chip exists.
@retval FALSE TPM chip is not found.
**/
BOOLEAN
TisPcPresenceCheck (
IN TIS_PC_REGISTERS_PTR TisReg
)
{
UINT8 RegRead;
RegRead = MmioRead8 ((UINTN)&TisReg->Access);
return (BOOLEAN)(RegRead != (UINT8)-1);
}
/**
Check whether the value of a TPM chip register satisfies the input BIT setting.
@param[in] Register Address port of register to be checked.
@param[in] BitSet Check these data bits are set.
@param[in] BitClear Check these data bits are clear.
@param[in] TimeOut The max wait time (unit MicroSecond) when checking register.
@retval EFI_SUCCESS The register satisfies the check bit.
@retval EFI_TIMEOUT The register can't run into the expected status in time.
**/
EFI_STATUS
EFIAPI
TisPcWaitRegisterBits (
IN UINT8 *Register,
IN UINT8 BitSet,
IN UINT8 BitClear,
IN UINT32 TimeOut
)
{
UINT8 RegRead;
UINT32 WaitTime;
for (WaitTime = 0; WaitTime < TimeOut; WaitTime += 30){
RegRead = MmioRead8 ((UINTN)Register);
if ((RegRead & BitSet) == BitSet && (RegRead & BitClear) == 0)
return EFI_SUCCESS;
MicroSecondDelay (30);
}
return EFI_TIMEOUT;
}
/**
Get BurstCount by reading the burstCount field of a TIS regiger
in the time of default TIS_TIMEOUT_D.
@param[in] TisReg Pointer to TIS register.
@param[out] BurstCount Pointer to a buffer to store the got BurstConut.
@retval EFI_SUCCESS Get BurstCount.
@retval EFI_INVALID_PARAMETER TisReg is NULL or BurstCount is NULL.
@retval EFI_TIMEOUT BurstCount can't be got in time.
**/
EFI_STATUS
EFIAPI
TisPcReadBurstCount (
IN TIS_PC_REGISTERS_PTR TisReg,
OUT UINT16 *BurstCount
)
{
UINT32 WaitTime;
UINT8 DataByte0;
UINT8 DataByte1;
if (BurstCount == NULL || TisReg == NULL) {
return EFI_INVALID_PARAMETER;
}
WaitTime = 0;
do {
//
// TIS_PC_REGISTERS_PTR->burstCount is UINT16, but it is not 2bytes aligned,
// so it needs to use MmioRead8 to read two times
//
DataByte0 = MmioRead8 ((UINTN)&TisReg->BurstCount);
DataByte1 = MmioRead8 ((UINTN)&TisReg->BurstCount + 1);
*BurstCount = (UINT16)((DataByte1 << 8) + DataByte0);
if (*BurstCount != 0) {
return EFI_SUCCESS;
}
MicroSecondDelay (30);
WaitTime += 30;
} while (WaitTime < TIS_TIMEOUT_D);
return EFI_TIMEOUT;
}
/**
Set TPM chip to ready state by sending ready command TIS_PC_STS_READY
to Status Register in time.
@param[in] TisReg Pointer to TIS register.
@retval EFI_SUCCESS TPM chip enters into ready state.
@retval EFI_INVALID_PARAMETER TisReg is NULL.
@retval EFI_TIMEOUT TPM chip can't be set to ready state in time.
**/
EFI_STATUS
EFIAPI
TisPcPrepareCommand (
IN TIS_PC_REGISTERS_PTR TisReg
)
{
EFI_STATUS Status;
if (TisReg == NULL) {
return EFI_INVALID_PARAMETER;
}
MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY);
Status = TisPcWaitRegisterBits (
&TisReg->Status,
TIS_PC_STS_READY,
0,
TIS_TIMEOUT_B
);
return Status;
}
/**
Get the control of TPM chip by sending requestUse command TIS_PC_ACC_RQUUSE
to ACCESS Register in the time of default TIS_TIMEOUT_D.
@param[in] TisReg Pointer to TIS register.
@retval EFI_SUCCESS Get the control of TPM chip.
@retval EFI_INVALID_PARAMETER TisReg is NULL.
@retval EFI_NOT_FOUND TPM chip doesn't exit.
@retval EFI_TIMEOUT Can't get the TPM control in time.
**/
EFI_STATUS
EFIAPI
TisPcRequestUseTpm (
IN TIS_PC_REGISTERS_PTR TisReg
)
{
EFI_STATUS Status;
if (TisReg == NULL) {
return EFI_INVALID_PARAMETER;
}
if (!TisPcPresenceCheck (TisReg)) {
return EFI_NOT_FOUND;
}
MmioWrite8((UINTN)&TisReg->Access, TIS_PC_ACC_RQUUSE);
Status = TisPcWaitRegisterBits (
&TisReg->Access,
(UINT8)(TIS_PC_ACC_ACTIVE |TIS_PC_VALID),
0,
TIS_TIMEOUT_D
);
return Status;
}

View File

@@ -0,0 +1,50 @@
/** @file
Basic TPM command functions.
Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "CommonHeader.h"
/**
Single function calculates SHA1 digest value for all raw data. It
combines Sha1Init(), Sha1Update() and Sha1Final().
@param[in] Data Raw data to be digested.
@param[in] DataLen Size of the raw data.
@param[out] Digest Pointer to a buffer that stores the final digest.
@retval EFI_SUCCESS Always successfully calculate the final digest.
**/
EFI_STATUS
EFIAPI
TpmCommHashAll (
IN CONST UINT8 *Data,
IN UINTN DataLen,
OUT TPM_DIGEST *Digest
)
{
VOID *Sha1Ctx;
UINTN CtxSize;
CtxSize = Sha1GetContextSize ();
Sha1Ctx = AllocatePool (CtxSize);
ASSERT (Sha1Ctx != NULL);
Sha1Init (Sha1Ctx);
Sha1Update (Sha1Ctx, Data, DataLen);
Sha1Final (Sha1Ctx, (UINT8 *)Digest);
FreePool (Sha1Ctx);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,46 @@
## @file
# TpmCommLib instance implements basis TPM Interface Specification (TIS) and TPM command functions.
#
# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = TpmCommLib
FILE_GUID = 7d9fe32e-a6a9-4cdf-abff-10cc7f22e1c9
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
LIBRARY_CLASS = TpmCommLib|DXE_DRIVER UEFI_DRIVER PEIM DXE_SMM_DRIVER
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF
#
[Sources]
TisPc.c
TpmComm.c
CommonHeader.h
[Packages]
MdePkg/MdePkg.dec
SecurityPkg/SecurityPkg.dec
CryptoPkg/CryptoPkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
IoLib
TimerLib
BaseCryptLib
MemoryAllocationLib
DebugLib