summaryrefslogtreecommitdiff
path: root/Core/EM/SecurityPkg/ImageVerificationLib
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/SecurityPkg/ImageVerificationLib')
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.c2431
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.h175
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/EfiImage.h702
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.cif12
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.mak92
-rw-r--r--Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.sdl109
6 files changed, 3521 insertions, 0 deletions
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.c b/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.c
new file mode 100644
index 0000000..7593b20
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.c
@@ -0,0 +1,2431 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/DxeImageVerificationLib.c 79 6/22/15 6:26p Alexp $
+//
+// $Revision: 79 $
+//
+// $Date: 6/22/15 6:26p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/DxeImageVerificationLib.c $
+//
+// 79 6/22/15 6:26p Alexp
+// EIP219415
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] UEFI PXE can launch unsigned images when
+// SecureBoot is enabled.
+// [RootCause] Image from PXE server gets cloned device path
+// from its parent network controller with PciIo protocol
+// and embedded PCI ROM attributes
+// [Solution] Add checking for unique path for embedded
+// Pci OpROMs to prevent non-OpROM images
+//
+// 77 5/14/15 9:49a Alexp
+// DxeImageVerificationHandler()
+// Modify certificate offset calculation to match EDKII version
+//
+// 76 3/09/15 4:24p Alexp
+// EIP192504: Prevent Built In EFI Shell boot option from being created in
+// BDS when Secure Boot is enabled
+// [Resolution]: Leave old logic to allow launching embedded shell
+// based on the token:LOAD_UNSIGNED_EMBEDDED_SHELL
+// enabled by default only in Debug mode
+// EIP197749: Need to authenticate images loaded from external FV
+// [Resolution] Add logic inside GetImageType() to detect images loaded
+// from external FV
+//
+// 75 5/29/14 8:52a Alexp
+// minor debug trace message change;
+//
+// 74 8/15/13 11:29a Alexp
+// EIP#118850: Implement support for Certificate Revocation Storage
+// reduction and Timestamp Support.
+// Link AmyCryptoLib to make use of os_mktime()
+//
+// 73 7/26/13 3:40p Alexp
+// 1. EIP118850: Integrate ECR1009 chnages for TimeStamp dbt processing
+// 2. Image policy settings are checked against the build time defaults.
+// Prevents un-authorized change to NVRAM policy settings
+// to lower security policy.
+//
+// 72 6/26/13 10:48a Alexp
+// EIP[125931]: Security review. Fix after follow up review.
+// UINT32 integer wrapping still occurs due to incorrect placement
+// of delimiting parentheses
+//
+// 70 6/25/13 7:21p Alexp
+// EIP:127292 Item#2. Add dependency on ENABLE_IMAGE_EXEC_POLICY_OVERRIDE
+// EIP:127292 Item#3 Only For deprecated Security protocol:
+// DxeImageVerificationHandler Returns Error if FileRead() is
+// unsuccessful
+//
+// 67 6/21/13 10:41a Alexp
+// EIP[125931]: Security review: HashPeImage does not validate certificate
+// table offset and size
+//
+// 66 5/21/13 4:05p Alexp
+// EIP:124444 Secure boot improvement for LoadImage call with NULL
+// DevicePath
+// EIP:122339 GetImageType() detect if PciOpROM image is loaded from
+// internal FV by
+// checking the corresponding PCI I/O instance for the embedded
+// attribute.
+//
+// 63 3/25/13 3:41p Alexp
+// 1. EIP:118243 add support for multi-signed PE Images
+// 2. Removed append image certificates to db from User Query dialog.
+//
+// 56 3/11/13 5:07p Alexp
+// IsSignatureFoundInDatabase(): fix method to calculate CertCount.
+// AddImageExeInfo(): code cleanup for cases when *Name is NULL
+// DxeImageVerificationHandler(): Optimized code to determine if PE image
+// is signed
+//
+// 55 3/09/13 4:31p Alexp
+// EIP114998: wrong cert size passed in PCR[7] calculation
+//
+// 54 12/19/12 10:28a Alexp
+// EIP[104046]: Hardened code per #2,3,4,5,6,7 of security review findings
+//
+//
+// 53 12/17/12 3:10p Alexp
+// code fixes according to "cppcheck" style & performance suggestions
+//
+// 52 12/06/12 7:31p Alexp
+// Update ImageAuthorization()
+//
+// 51 11/26/12 10:46a Alexp
+// replaced hardwired Var name L"SecureBootSetup" to generic Var define
+//
+// 50 11/19/12 4:42p Alexp
+// Fix for Win8 SecureBoot logo requirement: restore Secure Boot state
+// across flash updates.
+// Move all secure boot Setup settings to a separate varsore variable.
+// Preserve var across re-flash
+//
+// 49 11/09/12 4:32p Alexp
+// IsPkcsSignedDataVerifiedBySignatureList()
+// Fix CertData size - excude EFI_GUID size
+//
+// 48 10/17/12 3:03p Alexp
+// EIP[104046]: Findings from Security review on Aptio4 Image verification
+// Includes the fix for item #4:
+// HashPeImage returns TRUE even in error case
+//
+// 47 10/16/12 3:53p Alexp
+// EIP[104046]: Findings from Security review on Aptio4 Image verification
+// Includes the fix for item #7 from the list attached to the EIP
+//
+// 46 9/25/12 11:22a Alexp
+// removed ImageVerify simulation when system in SetupMode.
+//
+// 45 9/24/12 12:26p Alexp
+// fix code branch for WIN_CERT_TYPE_EFI_GUID certificates
+//
+// 44 9/19/12 4:07p Alexp
+// fix code branch to set action EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED
+//
+// 43 9/14/12 3:42p Alexp
+// Hardwire LoadFromFv to AlwaysEnable irrespective of SetupData
+//
+// 42 9/13/12 11:38a Alexp
+// Fix Bug in HashPeiImage.
+// Last step 16 in hashing of optional data structures after the
+// Certificate entry was missing
+//
+// 41 9/07/12 9:37a Alexp
+// 1. Set all global variables Static
+// 2. IsPkcsSignedDataVerifiedBySignatureList(). Compiler optimization for
+// "IsVerified = VerifyWinCertificateForPkcsSignedData(
+// &(PkcsCertData->Hdr));"
+// may not link the main code.
+// 3. Run Verify code when platform is in SetupMode and SecureBoot set to
+// Custom
+//
+// 39 9/05/12 5:42p Alexp
+// GetImageType() :
+// Change Device Path search criteria to match EDKII example:
+// check FV path first and then Block I/O
+//
+// 38 8/29/12 11:16a Alexp
+// Add definition for EFI_MAX_ADDRESS if it's not defined elsewhere in
+// included header files
+//
+// 37 8/28/12 4:21p Alexp
+// Restore dependencies on SecureBootMode->Custom Setup option
+//
+// 35 8/15/12 4:16p Alexp
+// IsPkcsSignedDataVerifiedBySignatureList()
+// Fix bug prev version in processing multiple Certs from PE Hdr.
+//
+// 34 7/26/12 3:54p Alexp
+// Query User -> Append Certificate only available in Setup Mode.
+//
+// 33 7/25/12 6:45p Alexp
+// 1. Update ImageVerification logic to the latest EDK2 patch (13469)
+// Add support for multiple Signatures within PE/COFF table
+// Additional Header validation checks
+// 2. Add code flow when SecureBoot set to Custom mode.
+// Image Verification is performed but failing images are allowed to
+// run
+// Use this mode to append image certificates to DB in User Query mode.
+//
+// 32 6/11/12 3:15p Alexp
+// use modified WIN_CERTIFICATE_UEFI_GUID_1 struc in
+// AppendEfiImageSecurityDatabaseVariableEx()
+// moded struc is shorter by 4 bytes
+//
+// 30 5/18/12 9:21a Alexp
+// Fine tune User Query messages. Only display the messages if Admin user
+// has signed in
+//
+// 29 5/01/12 4:43p Alexp
+// PCR[7] - mTrustSigDbOffs contains offset to SigData struct within SigDb
+//
+// 28 4/27/12 3:57p Alexp
+// Fix Certificate type in AppendEfiImageSecurityDatabaseVariableEx()
+//
+// 27 4/23/12 5:19p Alexp
+// EIP:80874 Made changes to support PCR[7] measurments for Secure Boot
+// state in TCG
+// Install "Efi Boot Image Certificate" info strusture on Efi System
+// Table.
+//
+// 26 4/20/12 5:14p Alexp
+// Add new function to install the handle on Efi System Table with the
+// location
+// within DB variable of the Trusted Certificate that was used to verify
+// signature of Efi OS BootLoader image.
+//
+// 25 4/10/12 6:52p Alexp
+// Update VerifyCertPkcsSignedData() to support extended search in
+// Forbidded db for any leaf certificate, not only Root CA
+//
+// 23 4/03/12 7:35p Alexp
+// Move ReadImage() under legacy SecureFileAuthentication()
+//
+// 22 4/02/12 4:24p Alexp
+// Installs EFI_SECURITY2_ARCH_PROTOCOL.
+// Input arguments include File Path and pointer to a File buffer in
+// memory.
+//
+// 20 3/20/12 10:51a Alexp
+// 1. fix in AppendEfiImageSecurityDatabaseVariableEx()
+// 2. removed unused global vars
+//
+// 18 3/16/12 10:29a Alexp
+// [EIP85500] Build problem with (INT)4.6.5.1_SECUREBOOT_WIN8_11
+// move "extern EFI_GUID BdsConnectDriversProtocolGuid " outside of #ifdef
+// scope
+//
+// 17 3/13/12 2:41p Alexp
+// Add check for Admin signed credentials while allowing User Querry
+// policy
+//
+// 16 3/12/12 3:01p Alexp
+// 1. Deffer image verification till BdsConnectDriversProtocol event.
+// Speeds up the boot time.
+// 2. Enforce default (hardwired by SDL token) image veriication policy
+// for image device path if SecureBootMode is set to Standard.
+//
+// 15 3/09/12 3:39p Alexp
+// 1. Fixed Image authentication by Hash certificate in "db"
+// 2. Add User interructive controls to append image certificate to Sig
+// "db" (test implementation, will change in later releases)
+//
+// 14 2/27/12 6:47p Alexp
+// Reduce time spent in the DxeImageVerificationHandler function during
+// non-Secure Boot mode. Original code caused additional 0.5 sec to boot
+// time.
+// Note: internal SecureBoot mode flag once registered during
+// initializaton - will not change until restart.
+//
+// 13 1/04/12 3:27p Alexp
+// Fixed possible security risk:
+// GetImageType(). Block I/O Device Path check made higher priority then
+// of FV device path.
+//
+// 12 12/29/11 6:49p Alexp
+// GetImageType() - Fix for Image Device Path resolution
+// Added SubType = MEDIA_FV_FILEPATH_DP to search options for
+// MEDIA_DEVICE_PATH.
+// It appears SmmDriverDispatcher sets this device path for files loaded
+// by SmmDispatcher.
+//
+// 11 12/23/11 8:59a Alexp
+// Bug fix:
+// EIP:78978:Secure boot will hang at CP 0x72
+// ConOut & ConIn are not available until later in BDS phase, earlier
+// calls to display User Prompt may hang the system
+//
+// 10 12/07/11 7:23p Alexp
+// Bug fix:
+// EIP:77088 SecureBoot: Image can be loaded if click "No" when query
+// user after image verification failed
+// ImageAuthorization() -> Return EFI_ACCESS_DENIED of User Override
+// option
+//
+// 9 8/22/11 11:14a Alexp
+// optimizations to GetImageType()
+//
+// 6 7/18/11 4:12p Alexp
+// EIP:65085. LoadImage Error status is different When Secure Boot is ON
+// EIP:65194: No way to control the Secure Boot module to not interact
+// with the USER without changing the code
+//
+// 4 6/23/11 9:27a Alexp
+// moved mDigitalSig Protocol check up before API may be called
+//
+// 3 6/22/11 5:45p Alexp
+// draft change: add Sha256 as valid cert for "db" databases
+//
+// 2 6/13/11 7:21p Alexp
+// fix Hash calculation for Sha256 Certs in Forbidden database dbx
+//
+// 10 5/17/11 5:36p Alexp
+// update conOut messages
+//
+// 9 5/17/11 12:50p Alexp
+// replace AmiPostManager with pST->ConOut
+// use pBS instead of gBS
+//
+// 6 5/13/11 4:02p Alexp
+// 1. add dependency on Core rev. 4.6.5+ to buld for older Aptio cores
+// 2. Ignore Querry User policy for internal FV files
+//
+//**********************************************************************
+/*++
+ This file contains an 'Intel Peripheral Driver' and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+--*/
+/** @file
+
+ Implement image verification services for secure boot
+ service in UEFI2.2.
+
+ Caution: This file requires additional review when modified.
+ This library will have external input - PE/COFF image.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ DxeImageVerificationLibImageRead() function will make sure the PE/COFF image content
+ read is within the image buffer.
+
+ DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept
+ untrusted PE/COFF image and validate its data structure within this image buffer before use.
+
+Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+**/
+
+#pragma warning (disable : 4090)
+
+#include <Token.h>
+#include <Protocol/Security.h>
+#include "DxeImageVerificationLib.h"
+#include "EfiImage.h"
+#include <AmiDxeLib.h>
+#include<Guid/PeiPeCoffLoader.h>
+#include <Protocol/AmiDigitalSignature.h>
+#include <AmiCertificate.h>
+#include <Setup.h>
+#include <SecureBootMod.h>
+#include <Protocol/PciIo.h> //EIP 122339
+#include <cryptlib.h>
+
+extern EFI_GUID BdsConnectDriversProtocolGuid;
+
+// 4.6.5.4
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028e
+#include <Protocol/Security2.h>
+#endif
+
+// 4.6.5.1
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028b
+#include <EdkIICommon.h>
+#else
+#include <Tiano.h>
+
+//********tmp declaration from EdkIICommon.h
+#define MEDIA_RELATIVE_OFFSET_RANGE_DP 0x08
+
+extern VOID ZeroMem (
+ OUT VOID *Buffer,
+ IN UINTN Size
+);
+VOID* CopyMem (
+ OUT VOID *DestinationBuffer,
+ IN VOID *SourceBuffer,
+ IN UINTN Length
+);
+#endif
+EFI_STATUS
+EFIAPI
+PeCoffLoaderGetImageInfo (
+ IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,
+ IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ );
+
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextOut.h>
+
+#define AMI_MEDIA_DEVICE_PATH_GUID \
+ { 0x5023b95c, 0xdb26, 0x429b, 0xa6, 0x48, 0xbd, 0x47, 0x66, 0x4c, 0x80, 0x12 }
+
+#define STANDARD_SECURE_BOOT 0
+#define CUSTOM_SECURE_BOOT 1
+
+static EFI_GUID AmiMediaDevicePathGuid = AMI_MEDIA_DEVICE_PATH_GUID;
+static EFI_GUID gSecureSetupGuid = SECURITY_FORM_SET_GUID;
+static EFI_GUID gEfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE;
+
+static AMI_DIGITAL_SIGNATURE_PROTOCOL *mDigitalSigProtocol = NULL;
+//
+// Caution: This is used by a function which may receive untrusted input.
+// These global variables hold PE/COFF image data, and they should be validated before use.
+//
+EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
+static UINT8 *mImageBase = NULL;
+static UINTN mImageSize;
+static EFI_GUID *mCertType;
+static UINT32 mPeCoffHeaderOffset;
+static UINT8 mImageDigest[MAX_DIGEST_SIZE];
+static UINTN mImageDigestSize;
+static SECURE_BOOT_SETUP_VAR mSecureBootSetup;
+static UINT8 mSecureBootEnable = 0;
+static UINTN mFvHandlesCount = 0;
+static EFI_HANDLE *mFvHandles = NULL;
+static BOOLEAN gImageLoadingAfterBDS = FALSE;
+
+//
+// Notify string for authorization UI.
+//
+CHAR16 mNotifyString1[MAX_NOTIFY_STRING_LEN] = L"\r\nImage verification failed!\r\n";
+CHAR16 mNotifyString2[MAX_NOTIFY_STRING_LEN] = L"\r\nLaunch this image anyway? (Y/N)";
+CHAR16 mNotifyString3[MAX_NOTIFY_STRING_LEN] = L"Image Certificate not found in Authorized database(db)!";
+CHAR16 mNotifyString4[MAX_NOTIFY_STRING_LEN] = L"Image Certificate is found in Forbidden database(dbx)!";
+CHAR16 mNotifyString5[MAX_NOTIFY_STRING_LEN] = L"Image is unsigned or Certificate is invalid!";
+
+//6683D10C-CF6E-4914-B5B4-AB8ED7370ED7
+EFI_GUID gBootImageCertTblGuid = AMI_VALID_BOOT_IMAGE_CERT_TBL_GUID;
+static UINT32 mTrustSigDbOffs = 0;
+static UINT32 mTrustSigDbSize = 0;
+
+//---------------------------------------
+// NEW TIME STAMP definitions ECR#1009
+//---------------------------------------
+extern EFI_GUID gEfiCertX509Sha256Guid;
+extern EFI_GUID gEfiCertX509Sha384Guid;
+extern EFI_GUID gEfiCertX509Sha512Guid;
+static INT32 mTimeOfSigningLong;
+typedef enum {
+ CertUndefined,
+ CertSha256,
+ CertX509,
+ CertX509Sha256,
+ CertX509Sha384,
+ CertX509Sha512,
+} nCertType;
+//---------------------------------------
+// NEW TIME STAMP definitions ECR#1009
+//---------------------------------------
+
+//************TEMP UTILITY FUNCTIONS. Use EDKII common wrapper lib instead****************
+#if defined(CORE_COMBINED_VERSION) && CORE_COMBINED_VERSION >=0x4028b
+#else
+UINTN StrSize (
+ IN CHAR16 *String)
+{
+ UINTN Size;
+
+ for (Size = 2; *String != L'\0'; String++, Size += 2);
+
+ return Size;
+}
+#endif
+
+VOID* GetEfiGlobalVariableEx (
+ IN CHAR16 *Name,
+ IN OUT UINTN *VarSize
+ )
+{
+ EFI_STATUS Status;
+ VOID *Var=NULL;
+
+ Status = GetEfiVariable(Name, &gEfiGlobalVariableGuid, NULL, VarSize, &Var);
+ return (EFI_ERROR(Status)) ? NULL : Var;
+}
+
+VOID* GetEfiImageSecurityDatabaseVariableEx (
+ IN CHAR16 *Name,
+ IN OUT UINTN *VarSize
+ )
+{
+ EFI_STATUS Status;
+ VOID *Var = NULL;
+
+ Status = GetEfiVariable(Name, &gEfiImageSecurityDatabaseGuid, NULL, VarSize, &Var);
+ return (EFI_ERROR(Status)) ? NULL : Var;
+}
+
+/**
+ Reads contents of a PE/COFF image in memory buffer.
+
+ Caution: This function may receive untrusted input.
+ PE/COFF image is external input, so this function will make sure the PE/COFF image content
+ read is within the image 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
+DxeImageVerificationLibImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ )
+{
+
+ if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((EFI_MAX_ADDRESS - FileOffset) < *ReadSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((UINT64)FileOffset + *ReadSize) > mImageSize) {
+// *ReadSize = (UINT32)(mImageSize - FileOffset);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FileOffset >= mImageSize) {
+// *ReadSize = 0;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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
+GetImageType (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ UINT8 nDevicePathSubType;
+ //EIP 122339 Start
+ EFI_PCI_IO_PROTOCOL *PciIoInterface = NULL;
+ UINT64 AttributesResult;
+ //EIP 122339 Stop
+ UINTN Index;
+ BOOLEAN IsFv = FALSE;
+
+ // Unknown device path: image security policy is applied to the image with the least trusted origin.
+ if (File == NULL) {
+ return IMAGE_UNKNOWN;
+ }
+
+ //
+ // Check if File is just a Firmware Volume.
+ //
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
+ while (!IsDevicePathEndType(TempDevicePath)){
+ nDevicePathSubType = DevicePathSubType (TempDevicePath);
+ TRACE((TRACE_ALWAYS,"Device PathType %x, SubType %x\n", DevicePathType(TempDevicePath), nDevicePathSubType ));
+ //
+ // EFI Specification extension on Media Device Path. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH is adopted by UEFI later and added in UEFI2.10.
+ // In EdkCompatibility Package, we only support MEDIA_FW_VOL_FILEPATH_DEVICE_PATH that complies with EFI 1.10 and UEFI 2.10.
+ //
+ if( (DevicePathType(TempDevicePath) == MEDIA_DEVICE_PATH && nDevicePathSubType == MEDIA_FV_FILEPATH_DP) ||
+ (DevicePathType(TempDevicePath) == HARDWARE_DEVICE_PATH && nDevicePathSubType == HW_MEMMAP_DP)
+ ){
+ IsFv = TRUE;
+ } else {
+ IsFv = FALSE;
+ break;
+ }
+ TempDevicePath = NextDevicePathNode(TempDevicePath);
+ }
+
+ //
+ // Check to see if a File or a FV is from internal Firmware Volume.
+ //
+ if(IsFv) {
+
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
+ Status = pBS->LocateDevicePath (
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ &gEfiFirmwareVolumeProtocolGuid,
+#else
+ &gEfiFirmwareVolume2ProtocolGuid,
+#endif
+ &TempDevicePath,
+ &DeviceHandle
+ );
+
+ if (!EFI_ERROR (Status)) {
+ if(!gImageLoadingAfterBDS)
+ return IMAGE_FROM_FV;
+
+ Status = pBS->OpenProtocol (
+ DeviceHandle,
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ &gEfiFirmwareVolumeProtocolGuid,
+#else
+ &gEfiFirmwareVolume2ProtocolGuid,
+#endif
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ for(Index=0;Index < mFvHandlesCount;Index++){
+ TRACE((TRACE_ALWAYS,"FV%02d. DeviceHandle %X=%X\n", Index, DeviceHandle, mFvHandles[Index] ));
+ if(DeviceHandle == mFvHandles[Index] )
+ return IMAGE_FROM_FV;
+ }
+ }
+ }
+ return IMAGE_UNKNOWN;
+ }
+ //
+ // Next check to see if File is from a Block I/O device
+ // Must be a Block I/O device since we reached here after Int FV path check
+ //
+ DeviceHandle = NULL;
+ TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File;
+ Status = pBS->LocateDevicePath (
+ &gEfiBlockIoProtocolGuid,
+ &TempDevicePath,
+ &DeviceHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ BlockIo = NULL;
+ Status = pBS->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 = pBS->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)) {
+ nDevicePathSubType = DevicePathSubType (TempDevicePath);
+ switch (DevicePathType (TempDevicePath)) {
+ //EIP 219415 Start
+ //Embedded OpROM
+ case HARDWARE_DEVICE_PATH:
+
+ if(nDevicePathSubType == HW_MEMMAP_DP) {
+ //EIP 122339 Start: Return IMAGE_FROM_FV if the EFI_PCI_IO_PROTOCOL installed
+ //on the same handle as the Device Path has the attribute EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
+ DeviceHandle = NULL;
+ //
+ // Check if an instance of the EFI_PCI_IO_PROTOCOL is installed on the same handle
+ // as the Device Path. If an instance is found WorkAroundDevHandle contains the
+ // handle for the Device Path and EFI_PCI_IO_PROTOCOL instance.
+ //
+ Status = pBS->LocateDevicePath(
+ &gEfiPciIoProtocolGuid,
+ &File,
+ &DeviceHandle
+ );
+ if(EFI_ERROR(Status)) break;
+
+ Status = pBS->HandleProtocol(
+ DeviceHandle,
+ &gEfiPciIoProtocolGuid,
+ &PciIoInterface
+ );
+
+ if(EFI_ERROR(Status)) break;
+
+ //
+ // Using the EFI_PCI_IO_PROTOCOL get the value of the PCI controller's
+ // Embedded Rom attribute (EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
+ //
+ Status = PciIoInterface->Attributes(
+ PciIoInterface,
+ EfiPciIoAttributeOperationGet,
+ 0, //this parameter is ignored during Get operation
+ &AttributesResult
+ );
+ if(EFI_ERROR(Status)) break;
+ //
+ // Check if the PCI controller's EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM is set
+ //
+ if(AttributesResult & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
+ return IMAGE_FROM_FV;
+ //EIP 122339 Stop
+ }
+ break;
+ //EIP 219415 end
+ case MEDIA_DEVICE_PATH:
+
+ if (nDevicePathSubType == MEDIA_RELATIVE_OFFSET_RANGE_DP) {
+ return IMAGE_FROM_OPTION_ROM;
+ }
+#if LOAD_UNSIGNED_EMBEDDED_SHELL == 1
+ // Case for embedded FV application such as Shell(check GUID. BootOptions.h)
+ if (nDevicePathSubType == MEDIA_VENDOR_DP &&
+ !guidcmp(&((VENDOR_DEVICE_PATH*)TempDevicePath)->Guid, &AmiMediaDevicePathGuid)) {
+ return IMAGE_FROM_FV;
+ }
+#endif
+ break;
+
+ case MESSAGING_DEVICE_PATH:
+
+ if (nDevicePathSubType == MSG_MAC_ADDR_DP) {
+ return IMAGE_FROM_REMOVABLE_MEDIA;
+ }
+ break;
+ }
+ TempDevicePath = NextDevicePathNode (TempDevicePath);
+ }
+
+ return IMAGE_UNKNOWN;
+}
+
+/**
+ Caculate hash of Pe/Coff image based on the authenticode image hashing in
+ PE/COFF Specification 8.0 Appendix A
+
+ 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] HashAlg Hash algorithm type.
+
+ @retval TRUE Successfully hash image.
+ @retval FALSE Fail in hash image.
+
+**/
+BOOLEAN
+HashPeImage (
+ IN UINT32 HashAlg
+ )
+{
+ EFI_STATUS EfiStatus;
+ BOOLEAN Status;
+ UINT16 Magic;
+ EFI_IMAGE_SECTION_HEADER *Section;
+ UINT8 *HashBase;
+ UINTN HashSize;
+ UINTN SumOfBytesHashed;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+ UINTN Index;
+ UINTN Pos;
+
+ const UINT8 *addr[MAX_ELEM_NUM]; // tbd. test if 20 elements is enough
+ UINTN num_elem, len[MAX_ELEM_NUM];
+ EFI_GUID *EfiHashAlgorithmGuid;
+
+ UINT32 CertSize;
+ UINT32 NumberOfRvaAndSizes;
+
+ SectionHeader = NULL;
+ Status = FALSE;
+ EfiStatus = EFI_SECURITY_VIOLATION;
+ num_elem = 0;
+ //
+ // Initialize context of hash.
+ //
+ ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
+ if (HashAlg == HASHALG_SHA1) {
+ mImageDigestSize = SHA1_DIGEST_SIZE;
+ EfiHashAlgorithmGuid = &gEfiHashAlgorithmSha1Guid;
+ mCertType = &gEfiCertSha1Guid;
+ } else if (HashAlg == HASHALG_SHA256) {
+ mImageDigestSize = SHA256_DIGEST_SIZE;
+ EfiHashAlgorithmGuid = &gEfiHashAlgorithmSha256Guid;
+ mCertType = &gEfiCertSha256Guid;
+ } else {
+ return FALSE;
+ }
+
+ // 1. Load the image header into memory.
+
+ //
+ // Measuring PE/COFF Image Header;
+ // But CheckSum field and SECURITY data directory (certificate) are excluded
+ //
+ if (mNtHeader.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
+ // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
+ // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+ // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ } else {
+ //
+ // Get the magic value from the PE/COFF Optional Header
+ //
+ Magic = mNtHeader.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 = mImageBase;
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);
+ NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
+ } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ //
+ // Use PE32+ offset.
+ //
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);
+ NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
+ } else {
+ //
+ // Invalid header magic number.
+ //
+ TRACE((TRACE_ALWAYS,"Invalid header magic number.\n"));
+ goto Done;
+ }
+
+ if (HashSize != 0)
+ {
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ } else {
+//TRACE((TRACE_ALWAYS,"Hash1.%x\n", HashSize));
+ goto Done;}
+ //
+ // 5. Skip over the image checksum (it occupies a single ULONG).
+ //
+ if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
+ //
+ // 6. Since there is no Cert Directory in optional header, hash everything
+ // from the end of the checksum to the end of image header.
+ //
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
+ HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
+ HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
+ }
+
+ if (HashSize != 0)
+ {
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ } else {
+//TRACE((TRACE_ALWAYS,"Hash2.%x\n", HashSize));
+ goto Done;}
+ } else {
+ //
+ // 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 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);
+ HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);
+ }
+ if (HashSize != 0)
+ {
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ } else {
+//TRACE((TRACE_ALWAYS,"Hash3.%x\n", HashSize));
+ goto Done;}
+
+ //
+ // 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 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
+ HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];
+ HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);
+ }
+ if (HashSize != 0)
+ {
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ } else {
+//TRACE((TRACE_ALWAYS,"Hash4.%x\n", HashSize));
+ goto Done;}
+ }
+
+ //
+ // 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 = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders;
+ } else {
+ //
+ // Use PE32+ offset
+ //
+ SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;
+ }
+
+
+ Section = (EFI_IMAGE_SECTION_HEADER *) (
+ mImageBase +
+ mPeCoffHeaderOffset +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader
+ );
+ //
+ // 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.
+ //
+// TRACE((TRACE_ALWAYS,"Num Sections = %x\n", mNtHeader.Pe32->FileHeader.NumberOfSections));
+
+// Security review [305408]: HashPeImage does not validate NumberOfSections field
+ Pos = sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections;
+ if(Pos > mImageSize)
+ goto Done;
+
+ EfiStatus = pBS->AllocatePool(EfiBootServicesData, Pos, &SectionHeader);
+ if (SectionHeader == NULL || EFI_ERROR(EfiStatus)) {
+//TRACE((TRACE_ALWAYS,"Hash4.\n"));
+ goto Done;
+
+ }
+ MemSet(SectionHeader, Pos, 0);
+ //
+ // 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.
+ //
+ for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
+ Pos = Index;
+
+ // Security review EIP[104046]:6. HashPeImage does not validate NumberOfSections field
+ if(((UINT64)Section + sizeof (EFI_IMAGE_SECTION_HEADER))> ((UINT64)mImageBase+mImageSize) )
+ goto Done;
+
+ 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 < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {
+ Section = &SectionHeader[Index];
+ if (Section->SizeOfRawData == 0) {
+ continue;
+ }
+
+//TRACE((TRACE_ALWAYS,"Section->PointerToRawData = %x\nSection->SizeOfRawData = %x\nSumOfBytesHashed = %x\n",Section->PointerToRawData, Section->SizeOfRawData, SumOfBytesHashed+Section->SizeOfRawData));
+ // Security review EIP[104046]: 5.HashPeImage does not validate PointerToRawData and SizeOfRawData fields
+ if( ((UINT64)Section->PointerToRawData + Section->SizeOfRawData) > mImageSize )
+ goto Done;
+
+ HashBase = mImageBase + Section->PointerToRawData;
+ HashSize = (UINTN) Section->SizeOfRawData;
+
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ if(num_elem >= MAX_ELEM_NUM)
+// goto Done;
+ {
+TRACE((TRACE_ALWAYS,"MAX_ELEM_NUM.1 = %d\n", num_elem));
+ goto Done;}
+ // Security review EIP[125931]: HashPeImage does not validate certificate table offset and size
+ if (((UINT64)SumOfBytesHashed+HashSize) > mImageSize)
+ goto Done;
+
+ 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)
+ //
+//dbg
+//TRACE((TRACE_ALWAYS,"mImageSize > SumOfBytesHashed.\n%x > %x\n", mImageSize, SumOfBytesHashed));
+//dbg
+ if (mImageSize > SumOfBytesHashed) {
+
+ HashBase = mImageBase + SumOfBytesHashed;
+
+ if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
+ CertSize = 0;
+ } else {
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ CertSize = mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ CertSize = mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
+ }
+ }
+
+ if (mImageSize > ((UINT64)CertSize + SumOfBytesHashed)) {
+ HashSize = (UINTN) (mImageSize - CertSize - SumOfBytesHashed);
+
+//TRACE((TRACE_ALWAYS,"\nData beyond nSumOfBytesHashed\nBase = %x, Size = %x\n",SumOfBytesHashed, HashSize));
+
+ addr[num_elem] = HashBase;
+ len[num_elem++] = HashSize;
+ if(num_elem >= MAX_ELEM_NUM)
+// goto Done;
+ {
+TRACE((TRACE_ALWAYS,"MAX_ELEM_NUM.2=%d\n", num_elem));
+ goto Done;}
+
+ } else if (mImageSize < ((UINT64)CertSize + SumOfBytesHashed)) {
+TRACE((TRACE_ALWAYS,"mImageSize < CertSize + SumOfBytesHashed.\n%d < %d\n", mImageSize, CertSize + SumOfBytesHashed));
+ goto Done;
+ }
+ else
+ HashSize = 0;
+ // ??? HashBase += CertSize;
+//TRACE((TRACE_ALWAYS,"\nData beyond CertDir\nBase = %x, Size = %x\n",SumOfBytesHashed+HashSize+CertSize, mImageSize-(SumOfBytesHashed+HashSize+CertSize)));
+ }
+ EfiStatus = mDigitalSigProtocol->Hash(
+ mDigitalSigProtocol,
+ EfiHashAlgorithmGuid, num_elem, addr, len, (UINT8*)&mImageDigest);
+
+TRACE((TRACE_ALWAYS,"Found HashElements %d\nImageHash: [%2X],[%2X],..\n", num_elem, mImageDigest[0], mImageDigest[1]));
+
+ if(!EFI_ERROR(EfiStatus))
+ Status = TRUE;
+
+Done:
+
+ if (SectionHeader != NULL) {
+ pBS->FreePool (SectionHeader);
+ }
+ // Security review EIP[104046]: 4.HashPeImage returns TRUE even in error case
+ // Status = FALSE unless updated to TRUE in the final Hash step before "Done" label
+ return Status;
+}
+
+/**
+ Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
+ Pe/Coff image based on the authenticode image hashing in PE/COFF Specification
+ 8.0 Appendix A
+
+ 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] AuthData Pointer to the Authenticode Signature retrieved from signed image.
+ @param[in] AuthDataSize Size of the Authenticode Signature in bytes.
+
+ @retval EFI_UNSUPPORTED Hash algorithm is not supported.
+ @retval EFI_SUCCESS Hash successfully.
+
+**/
+EFI_STATUS
+HashPeImageByType (
+ IN UINT8 *AuthData,
+ IN UINTN AuthDataSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 DigestAlgo;
+ UINT8 *pDigestAlgo;
+ UINTN Size;
+
+// get Digest Algorithm
+ Size = 0;
+ pDigestAlgo = (UINT8*)&DigestAlgo;
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ AuthData,
+ AuthDataSize,
+ NULL,
+ 0,
+ &pDigestAlgo, // returns DER Ptr to Sign Cert
+ &Size,
+ Pkcs7GetDigestAlgorithm,
+ LOCK
+ );
+ if (EFI_ERROR(Status))
+ return Status;
+
+ switch(DigestAlgo) {
+ case SHA1:
+ if (!HashPeImage (HASHALG_SHA1)) {
+ Status = EFI_SECURITY_VIOLATION;
+ }
+ break;
+ case SHA256:
+ if (!HashPeImage (HASHALG_SHA256)) {
+ Status = EFI_SECURITY_VIOLATION;
+ }
+ break;
+ default:
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Returns the size of a given image execution info table in bytes.
+
+ This function returns the size, in bytes, of the image execution info table specified by
+ ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned.
+
+ @param ImageExeInfoTable A pointer to a image execution info table structure.
+
+ @retval 0 If ImageExeInfoTable is NULL.
+ @retval Others The size of a image execution info table in bytes.
+
+**/
+UINTN
+GetImageExeInfoTableSize (
+ EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable
+ )
+{
+ UINTN Index;
+ EFI_IMAGE_EXECUTION_INFO *ImageExeInfoItem;
+ UINTN TotalSize;
+
+ if (ImageExeInfoTable == NULL) {
+ return 0;
+ }
+
+ ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoTable + sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE));
+ TotalSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
+ for (Index = 0; Index < ImageExeInfoTable->NumberOfImages; Index++) {
+ TotalSize += ImageExeInfoItem->InfoSize;
+ ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoItem + ImageExeInfoItem->InfoSize);
+ }
+
+ return TotalSize;
+}
+
+/**
+ Create an Image Execution Information Table entry and add it to system configuration table.
+
+ @param[in] Action Describes the action taken by the firmware regarding this image.
+ @param[in] Name Input a null-terminated, user-friendly name.
+ @param[in] DevicePath Input device path pointer.
+ @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
+ @param[in] SignatureSize Size of signature.
+
+**/
+VOID
+AddImageExeInfo (
+ IN EFI_IMAGE_EXECUTION_ACTION Action,
+ IN CHAR16 *Name OPTIONAL,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_SIGNATURE_LIST *Signature OPTIONAL,
+ IN UINTN SignatureSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable;
+ EFI_IMAGE_EXECUTION_INFO_TABLE *NewImageExeInfoTable;
+ EFI_IMAGE_EXECUTION_INFO *ImageExeInfoEntry;
+ UINTN ImageExeInfoTableSize;
+ UINTN NewImageExeInfoEntrySize;
+ UINTN NameStringLen;
+ UINTN DevicePathSize;
+
+ NewImageExeInfoTable = NULL;
+ ImageExeInfoEntry = NULL;
+ NameStringLen = sizeof (CHAR16);
+
+ if (DevicePath == NULL) {
+ return ;
+ }
+
+ if (Name != NULL) {
+ NameStringLen = StrSize (Name);
+ }
+
+ ImageExeInfoTable = GetEfiConfigurationTable(pST, &gEfiImageSecurityDatabaseGuid);
+ if (ImageExeInfoTable != NULL) {
+ //
+ // The table has been found!
+ // We must enlarge the table to accmodate the new exe info entry.
+ //
+ ImageExeInfoTableSize = GetImageExeInfoTableSize (ImageExeInfoTable);
+ } else {
+ //
+ // Not Found!
+ // We should create a new table to append to the configuration table.
+ //
+ ImageExeInfoTableSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE);
+ }
+
+ DevicePathSize = DPLength(DevicePath);
+ NewImageExeInfoEntrySize = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;
+
+ Status = pBS->AllocatePool(EfiRuntimeServicesData, ImageExeInfoTableSize + NewImageExeInfoEntrySize, &NewImageExeInfoTable);
+ if(EFI_ERROR(Status)) return;
+
+ if (ImageExeInfoTable != NULL) {
+ CopyMem (NewImageExeInfoTable, ImageExeInfoTable, ImageExeInfoTableSize);
+ } else {
+ NewImageExeInfoTable->NumberOfImages = 0;
+ }
+ NewImageExeInfoTable->NumberOfImages++;
+ ImageExeInfoEntry = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) NewImageExeInfoTable + ImageExeInfoTableSize);
+ //
+ // Update new item's infomation.
+ //
+ ImageExeInfoEntry->Action = Action;
+ ImageExeInfoEntry->InfoSize = (UINT32) NewImageExeInfoEntrySize;
+
+ if (Name != NULL) {
+ CopyMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), Name, NameStringLen);
+ } else {
+ ZeroMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), NameStringLen);
+ }
+ CopyMem (
+ (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen,
+ DevicePath,
+ DevicePathSize
+ );
+ if (Signature != NULL) {
+ CopyMem (
+ (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen + DevicePathSize,
+ Signature,
+ SignatureSize
+ );
+ }
+ //
+ // Update/replace the image execution table.
+ //
+ Status = pBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Free Old table data!
+ //
+ if (ImageExeInfoTable != NULL) {
+ pBS->FreePool (ImageExeInfoTable);
+ }
+}
+
+/**
+ Create a Boot Image Certificate table entry and add it to system configuration table.
+
+ @param[in] Name Input a null-terminated, user-friendly name.
+ @param[in] DevicePath Input device path pointer.
+ @param[in] Signature Input signature info in EFI_SIGNATURE_LIST data structure.
+ @param[in] SignatureSize Size of signature.
+
+**/
+VOID
+AddBootImageCertInfo (
+ IN CHAR16 *Name OPTIONAL,
+ IN UINT32 SignatureOffs,
+ IN UINT32 SignatureSize
+ )
+{
+ EFI_STATUS Status;
+ AMI_VALID_CERT_IN_SIG_DB *BootImageCertInfoTable;
+ UINTN BootImageCertInfoTableSize;
+
+ if(SignatureOffs == 0 || SignatureSize == 0)
+ return;
+
+ BootImageCertInfoTable = GetEfiConfigurationTable(pST, &gBootImageCertTblGuid);
+ if (BootImageCertInfoTable == NULL) {
+ //
+ // Not Found!
+ // We should create a new table.
+ //
+ BootImageCertInfoTableSize = sizeof (AMI_VALID_CERT_IN_SIG_DB);
+ Status = pBS->AllocatePool(EfiRuntimeServicesData, BootImageCertInfoTableSize, &BootImageCertInfoTable);
+ if(EFI_ERROR(Status)) return;
+ //
+ // Update/replace the image execution table.
+ //
+ Status = pBS->InstallConfigurationTable (&gBootImageCertTblGuid, (VOID *) BootImageCertInfoTable);
+ ASSERT_EFI_ERROR (Status);
+ TRACE((TRACE_ALWAYS,"Install BootImageCert Table ...%r\n", Status));
+ if (EFI_ERROR (Status)) return;
+ }
+ //
+ // Update Table's infomation.
+ //
+ BootImageCertInfoTable->SigOffset = SignatureOffs;
+ BootImageCertInfoTable->SigLength = SignatureSize;
+
+TRACE((TRACE_ALWAYS,"BootImage Cert in db\nOffset=%X\nLength=%X\n", BootImageCertInfoTable->SigOffset, BootImageCertInfoTable->SigLength));
+}
+
+/**
+ Discover if the UEFI image is authorized by user's policy setting.
+
+ @param[in] Policy Specify platform's policy setting.
+ @param[in] Action Image Validation status.
+
+ @retval EFI_ACCESS_DENIED Image is not allowed to run.
+ @retval EFI_SECURITY_VIOLATION Image is deferred.
+ @retval EFI_SUCCESS Image is authorized to run.
+
+**/
+EFI_STATUS
+ImageAuthorization (
+ IN UINT32 Policy,
+ IN UINT32 Action
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key = {0,0};
+ UINTN Index;
+ BOOLEAN bQuery;
+
+ Status = EFI_ACCESS_DENIED;
+
+ switch (Policy) {
+
+ case QUERY_USER_ON_SECURITY_VIOLATION:
+ // Conditions to allow overwrite of Execution Policy:
+ // 1. Output Console available
+ if((pST->ConIn != NULL && pST->ConOut != NULL))
+ {
+ pST->ConOut->OutputString(pST->ConOut, mNotifyString1);
+ bQuery = TRUE;
+ switch(Action) {
+ case EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND: // not found in db
+ pST->ConOut->OutputString(pST->ConOut, mNotifyString3);
+ break;
+ case EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND: // found in dbx
+ pST->ConOut->OutputString(pST->ConOut, mNotifyString4);
+ break;
+ case EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED:
+ case EFI_IMAGE_EXECUTION_AUTH_UNTESTED:
+ pST->ConOut->OutputString(pST->ConOut, mNotifyString5);
+ break;
+ default:
+ bQuery = FALSE;
+ break;
+ }
+ if(!bQuery) break;
+ //Wait for key
+ pST->ConOut->OutputString(pST->ConOut, mNotifyString2);
+Repeat:
+ pBS->WaitForEvent( 1, &pST->ConIn->WaitForKey, &Index );
+ Status = pST->ConIn->ReadKeyStroke( pST->ConIn, &Key );
+ if (!EFI_ERROR (Status)) {
+ if ((Key.UnicodeChar == L'y') || (Key.UnicodeChar == L'Y')) { //yes
+ Status = EFI_SUCCESS;
+ } else if ((Key.UnicodeChar == L'n') || (Key.UnicodeChar == L'N')) { //no
+ Status = EFI_ACCESS_DENIED;
+ } else {
+ goto Repeat;
+ }
+ }
+ pST->ConOut->OutputString(pST->ConOut, L"\r\n");
+ }
+ break;
+
+ case DEFER_EXECUTE_ON_SECURITY_VIOLATION:
+ Status = EFI_SECURITY_VIOLATION;
+ break;
+
+ // case DENY_EXECUTE_ON_SECURITY_VIOLATION:
+ default:
+ Status = EFI_ACCESS_DENIED;
+ break;
+ }
+
+TRACE((TRACE_ALWAYS,"Image Authorization policy...%r\n", Status));
+
+ return Status;
+}
+
+/**
+ Advanced check in Signature Database
+ Check whether signature is located in target database
+
+ @param[in] Signature Pointer to signature that is searched for.
+ @param[in] SignatureSize Size of Signature.
+ @param[in] SignatureType Type of the Certificate, Guid
+
+ @return TRUE - found in IsSigForbidden
+ @return FALSE
+
+**/
+BOOLEAN
+IsSignatureFoundInDatabase (
+ IN CHAR16 *Name,
+ EFI_GUID *SignatureType,
+ IN UINT8 *Signature,
+ IN UINTN SignatureSize
+ )
+{
+ EFI_SIGNATURE_LIST *CertList;
+ EFI_SIGNATURE_DATA *Cert;
+ UINT8 *Data;
+ UINTN DataSize;
+ UINTN Index;
+ UINTN CertCount;
+ BOOLEAN IsSigFound;
+
+ //
+ // Read signature database variable.
+ //
+ IsSigFound = FALSE;
+
+ //
+ // Get Signature Database variable.
+ //
+
+ Data = GetEfiImageSecurityDatabaseVariableEx (Name, &DataSize);
+
+ if (Data != NULL) {
+// not an error if no "dbx" defined
+ //
+ // Enumerate all signature data in SigDB to check if executable's signature exists.
+ //
+ CertList = (EFI_SIGNATURE_LIST *) Data;
+ while (!IsSigFound && (DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
+ if (!guidcmp(&CertList->SignatureType, SignatureType)) { // Cert types do match
+ CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+ if (CertList->SignatureSize == (sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize)) {
+ for (Index = 0; Index < CertCount; Index++) {
+ if (MemCmp(Cert->SignatureData, Signature, SignatureSize) == 0) {
+ //
+ // Find the signature in database.
+ //
+ IsSigFound = TRUE;
+ break;
+ }
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
+ }
+ }
+ } // next CertList
+ DataSize -= CertList->SignatureListSize;
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+ }
+ pBS->FreePool (Data);
+ }
+
+ return IsSigFound;
+}
+
+
+/**
+ Verify PKCS#7 SignedData using certificate found in Variable which formatted
+ as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
+
+ @param VariableName Name of Variable to search for Certificate.
+
+ @retval TRUE Image pass verification.
+ @retval FALSE Image fail verification.
+
+**/
+BOOLEAN
+IsPkcsSignedDataVerifiedBySignatureList (
+ IN UINT8 *AuthData,
+ IN UINTN AuthDataSize,
+ IN CHAR16 *VariableName,
+ IN UINT8 Operation
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIGNATURE_LIST *CertList;
+ EFI_SIGNATURE_DATA *Cert;
+ UINT32 CertCount;
+ UINT32 Index;
+ UINT8 *Data;
+ UINTN DataSize;
+ UINT8 *RootCert;
+ UINTN RootCertSize;
+ UINT8 *SigCert;
+ UINTN SigCertSize;
+ BOOLEAN IsVerified;
+ EFI_TIME *TimeStamp;
+ INT32 TimeOfRevocationLong;
+ UINT8 ValidCertType;
+ BOOLEAN bVerifyTimeStampStatus;
+ BOOLEAN bProcessVerifyTimeStampStatus;
+
+ CertList = NULL;
+ Cert = NULL;
+ RootCert = NULL;
+ RootCertSize = 0;
+ IsVerified = FALSE;
+ ValidCertType = CertUndefined;
+ bVerifyTimeStampStatus= FALSE;
+ bProcessVerifyTimeStampStatus = FALSE;
+
+ mTimeOfSigningLong = 0;
+ TimeOfRevocationLong = 0;
+ // Verify the certificate's header
+ //
+ // Find certificate in store and verify authenticode struct.
+ //
+ Data = GetEfiImageSecurityDatabaseVariableEx (VariableName, &DataSize);
+
+ if (!Data)
+ return IsVerified;
+
+TRACE((TRACE_ALWAYS,"\nLook for a match in '%S'===>\n\n", VariableName));
+
+ CertList = (EFI_SIGNATURE_LIST *)Data;
+
+ //
+ // TO DO Optimization.
+ // 1. Find Root CA Cert Ptr or Signer Cert if Root is not found
+ // 2. loop thru Trust Cert list and compare each one against Root CA cert(verify SignCert signature with Trust Cert)
+ // 3. If found, break the 'while' loop and Pkcs7Verify with Trust Cert
+ //
+ //
+ // Find Cert Enrolled in database to verify the signature in pkcs7 signed data.
+ //
+ // here should be a loop thru Cert list till CertCount
+ while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {
+
+ if(!guidcmp(&CertList->SignatureType, &gEfiCertX509Guid))
+ ValidCertType = CertX509;
+ else
+ if(!guidcmp(&CertList->SignatureType, mCertType))
+ ValidCertType = CertSha256;
+ else
+ if(!guidcmp(&CertList->SignatureType, &gEfiCertX509Sha256Guid))
+ ValidCertType = CertX509Sha256;
+ else
+ if(!guidcmp(&CertList->SignatureType, &gEfiCertX509Sha384Guid))
+ ValidCertType = CertX509Sha384;
+ else
+ if(!guidcmp(&CertList->SignatureType, &gEfiCertX509Sha512Guid))
+ ValidCertType = CertX509Sha512;
+
+ if (ValidCertType)
+ {
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+ CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+ RootCertSize = CertList->SignatureSize-sizeof(EFI_GUID); // sig data structure starts with SigOwner Guid
+TRACE((TRACE_ALWAYS,"Signature Type %g\nRootCertSize = %X\n",CertList->SignatureType, RootCertSize));
+
+ for (Index = 0; Index < CertCount; Index++) {
+ //
+ // Iterate each Signature Data Node within this CertList for verify.
+ //
+ RootCert = Cert->SignatureData;
+ switch(ValidCertType) {
+// is Sha256/Sha1
+ case CertSha256:
+ if(RootCertSize == mImageDigestSize &&
+ MemCmp(RootCert, mImageDigest, mImageDigestSize) == 0) {
+TRACE((TRACE_ALWAYS,"Hash Cert match found...\n"));
+ //
+ // Found the signature in database.
+ //
+ IsVerified = TRUE;
+ }
+ break;
+// x509, x509_ShaXXX
+/*
+Revocation is true:
+- return success && Time = 0
+- return success && Time != 0 && VerifyTimeStampStatus
+- success
+if success but mVerifyTimeStampStatus = ACCESS_DENIED = return FAIL
+timestamp non-0 Year > 0
+*/
+ case CertX509Sha256:
+ case CertX509Sha384:
+ case CertX509Sha512:
+ switch(ValidCertType) {
+ case CertX509Sha256:
+ TimeStamp = &((EFI_CERT_X509_SHA256*)RootCert)->TimeOfRevocation;
+ break;
+ case CertX509Sha384:
+ TimeStamp = &((EFI_CERT_X509_SHA384*)RootCert)->TimeOfRevocation;
+ break;
+ case CertX509Sha512:
+ TimeStamp = &((EFI_CERT_X509_SHA512*)RootCert)->TimeOfRevocation;
+ break;
+ }
+ // Check the timestamp cert validity the valid certificate in allowed database (dbt).
+ if(!bProcessVerifyTimeStampStatus) {
+ bVerifyTimeStampStatus = IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE2, Pkcs7TimeStampCertValidateGet);
+ bProcessVerifyTimeStampStatus = TRUE;
+ }
+ if(os_mktime(TimeStamp->Year, TimeStamp->Month, TimeStamp->Day, TimeStamp->Hour, TimeStamp->Minute, TimeStamp->Second,&TimeOfRevocationLong))
+ TimeOfRevocationLong = 0;
+TRACE((TRACE_ALWAYS,"\nTimeStamp cert validate %s\nTimeOfSigning %X\nTimeOfRevocation %X\n", (!bVerifyTimeStampStatus?"FAIL":"PASS"), mTimeOfSigningLong, TimeOfRevocationLong));
+ if(TimeOfRevocationLong) {
+ if(!bVerifyTimeStampStatus) {
+ IsVerified = TRUE; // found in dbx -> image is revoked!
+ break;
+ }
+ // keep looking for cert with sign time passed revocation
+ if(mTimeOfSigningLong < TimeOfRevocationLong)
+ break;
+ }
+ case CertX509:
+TRACE((TRACE_ALWAYS,"proceed with Pkcs7Verify...\n"));
+ //
+ //
+ // Verify Authenticode struct for image's current certificate.
+ //
+ // using protocol
+ SigCert = mImageDigest;
+ SigCertSize = mImageDigestSize;
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ AuthData,
+ AuthDataSize,
+ RootCert,
+ RootCertSize,
+ // mDigest, DigestLen
+ &SigCert,
+ &SigCertSize,
+ Operation, // Operation; Pkcs7CertValidate OR Pkcs7CertGetMatchInCertChain
+ KEEP // Flags
+ );
+TRACE((TRACE_ALWAYS,"====> %r\n", Status));
+ if (!EFI_ERROR(Status)) {
+ IsVerified = TRUE; // found matching certificate in the image
+ switch(Operation) {
+ case Pkcs7TimeStampCertValidateGet:
+ mTimeOfSigningLong = (INT32)SigCertSize;
+ break;
+ case Pkcs7CertValidate:
+ // only x509 certs frm db are measured in PCR[7]
+ mTrustSigDbOffs = (UINT32)(UINT8*)(((UINT8*)Cert-Data));
+ mTrustSigDbSize = CertList->SignatureSize;
+ break;
+ }
+ }
+ break;
+ default :
+ goto Exit;
+ } // switch
+ if (IsVerified)
+ {
+ goto Exit;
+ }
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
+ } // end for
+ } // end If
+
+ DataSize -= CertList->SignatureListSize;
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+ } // end while
+Exit:
+ pBS->FreePool (Data);
+TRACE((TRACE_ALWAYS,"\n<===%s cert match in '%S'\n",(IsVerified?"Got":"No"), VariableName));
+ return IsVerified;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DxeImageVerificationHandler
+//
+// Description: Handle for Security Architectural Protocol
+// 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 SHA256 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.
+//
+// Input:
+// File This is a pointer to the device path of the file that is
+// being dispatched. This will optionally be used for logging.
+// FileBuffer File buffer matches the input file device path.
+// FileSize Size of File buffer matches the input file device path.
+//
+// Output: EFI_STATUS
+//
+// EFI_SUCCESS The file specified by File did authenticate, and the
+// platform policy dictates that the DXE Core may use File.
+// EFI_INVALID_PARAMETER File is NULL.
+// 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.
+// 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.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+DxeImageVerificationHandler (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
+ IN VOID *FileBuffer,
+ IN UINTN FileSize,
+ IN BOOLEAN BootPolicy
+ )
+
+{
+ EFI_STATUS Status;
+ UINT16 Magic;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_STATUS VerifyStatus;
+ EFI_SIGNATURE_LIST *SignatureList;
+ UINTN SignatureListSize;
+ EFI_SIGNATURE_DATA *Signature;
+ EFI_IMAGE_EXECUTION_ACTION Action;
+ WIN_CERTIFICATE *WinCertificate;
+ UINT32 Policy;
+ BOOLEAN bFileRead;
+
+ EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ UINT32 NumberOfRvaAndSizes;
+
+ WIN_CERTIFICATE_EFI_PKCS *PkcsCertData;
+ WIN_CERTIFICATE_UEFI_GUID *WinCertUefiGuid;
+ UINT8 *AuthData;
+ UINTN AuthDataSize;
+ EFI_IMAGE_DATA_DIRECTORY *SecDataDir;
+ UINT32 OffSet;
+
+
+ SignatureList = NULL;
+ SignatureListSize = 0;
+ WinCertificate = NULL;
+ SecDataDir = NULL;
+ PkcsCertData = NULL;
+ Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
+ VerifyStatus = EFI_ACCESS_DENIED;
+ Status = EFI_ACCESS_DENIED;
+ bFileRead = FALSE;
+
+ mImageDigestSize = 0;
+ mCertType = NULL;
+ //
+ // Check the image type and get policy setting.
+ //
+ switch (GetImageType (File)) {
+
+ case IMAGE_FROM_FV:
+ Policy = ALWAYS_EXECUTE;
+ break;
+
+ case IMAGE_FROM_OPTION_ROM:
+ Policy = mSecureBootSetup.Load_from_OROM;
+ break;
+
+ case IMAGE_FROM_REMOVABLE_MEDIA:
+ Policy = mSecureBootSetup.Load_from_REMOVABLE_MEDIA;
+ break;
+
+ case IMAGE_FROM_FIXED_MEDIA:
+ Policy = mSecureBootSetup.Load_from_FIXED_MEDIA;
+ break;
+
+ default:
+TRACE((TRACE_ALWAYS,"Unknown Image Path\n"));
+ Policy = DENY_EXECUTE_ON_SECURITY_VIOLATION;
+ break;
+ }
+
+ //
+ // If policy is always/never execute, return directly.
+ //
+ if (Policy == ALWAYS_EXECUTE) {
+ return EFI_SUCCESS;
+ } else
+ if (Policy == NEVER_EXECUTE) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (FileBuffer == NULL) {
+ //
+ // Read the PE/COFF file.
+ //
+ TRACE((TRACE_ALWAYS,"FileAuthentication\nFileType = %x, SubType = %x\n", File->Type, File->SubType));
+ Status = ReadImage(FALSE, File, &FileBuffer, &FileSize, NULL, NULL, NULL);
+ TRACE((TRACE_ALWAYS,"File read(1)...%r\n", Status));
+ if(EFI_ERROR(Status)) {
+ Status = ReadImage(TRUE, File, &FileBuffer, &FileSize, NULL, NULL, NULL);
+ TRACE((TRACE_ALWAYS,"File read(2)...%r\n", Status));
+ if(EFI_ERROR(Status))
+ return EFI_ACCESS_DENIED;
+ }
+
+ bFileRead = TRUE;
+ }
+ //
+ // Read the Dos header.
+ //
+ ASSERT (FileBuffer != NULL);
+ if (FileBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ mImageBase = (UINT8 *) FileBuffer;
+ mImageSize = FileSize;
+
+ ZeroMem (&ImageContext, sizeof (ImageContext));
+ ImageContext.Handle = (VOID *) FileBuffer;
+ ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) DxeImageVerificationLibImageRead;
+
+ //
+ // Get information about the image being loaded
+ //
+ if (EFI_ERROR (PeCoffLoaderGetImageInfo (NULL, &ImageContext)) ||
+ ( mImageSize< sizeof(EFI_IMAGE_DOS_HEADER)) ) {
+ //
+ // The information can't be gotten from the invalid PeImage
+ //
+ TRACE((TRACE_ALWAYS,"PeCoffLoaderGetImageInfo Error\n"));
+ goto Done;
+ }
+
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ //
+ // DOS image header is present,
+ // so read the PE header after the DOS image header.
+ //
+ mPeCoffHeaderOffset = DosHdr->e_lfanew;
+ } else {
+ mPeCoffHeaderOffset = 0;
+ }
+ // Security review EIP[104046]: 3.HashPeImage does not validate minimum image size
+ // Validate mPeCoffHeaderOffset is within the Image size range
+ if(((UINT64)mPeCoffHeaderOffset+sizeof(EFI_IMAGE_NT_HEADERS32)) > mImageSize) {
+ TRACE((TRACE_ALWAYS,"EFI_IMAGE_NT_SIGNATURE Error\n"));
+ goto Done;
+ }
+
+ //
+ // Check PE/COFF image.
+ //
+ mNtHeader.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (mImageBase + mPeCoffHeaderOffset);
+ if (mNtHeader.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
+ //
+ // It is not a valid Pe/Coff file.
+ //
+ TRACE((TRACE_ALWAYS,"EFI_IMAGE_NT_SIGNATURE Error\n"));
+ goto Done;
+ }
+
+ if (mNtHeader.Pe32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
+ // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
+ // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+ // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ } else {
+ //
+ // Get the magic value from the PE/COFF Optional Header
+ //
+ Magic = mNtHeader.Pe32->OptionalHeader.Magic;
+ }
+
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use PE32 offset.
+ //
+ NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
+ if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
+ SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
+ }
+ } else {
+ //
+ // Use PE32+ offset.
+ //
+ NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
+ if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
+ SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
+ }
+ }
+
+ TRACE((TRACE_ALWAYS,"mImageSize %x\n", mImageSize));
+
+ //
+ // Start Image Validation.
+ //
+ if (SecDataDir && SecDataDir->Size) {
+ //
+ // Image is possibly signed
+ //
+ TRACE((TRACE_ALWAYS,"SecDataDir->VirtualAddress %x\nSecDataDir->Size = %x\nIMAGE is Signed\n",
+ SecDataDir->VirtualAddress, SecDataDir->Size));
+ // Security review EIP[104046]: 2.Multiple integer underflows calculating size of certificate data in PE file
+ if(((UINT64)SecDataDir->VirtualAddress+SecDataDir->Size) > mImageSize)
+ goto Done;
+
+ //
+ // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7
+ // "Attribute Certificate Table".
+ // The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.
+ //
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
+ for (OffSet = SecDataDir->VirtualAddress;
+ OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);
+// OffSet += WinCertificate->dwLength, OffSet += ALIGN_SIZE (OffSet)) {
+ OffSet +=(WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength))) {
+
+ WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
+ TRACE((TRACE_ALWAYS,"\nOffSet = %x, WinCertificate->dwLength %x\n\n", OffSet, WinCertificate->dwLength));
+ if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||
+ (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {
+ break;
+ }
+ //
+ // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.
+ //
+ //
+ // Verify signature of executables.
+ //
+
+ if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
+ //
+ // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the
+ // Authenticode specification.
+ //
+ PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;
+ if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {
+ break;
+ }
+ AuthData = PkcsCertData->CertData;
+ AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);
+
+ } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
+ //
+ // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.
+ //
+ WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;
+ if (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {
+ break;
+ }
+ if (guidcmp (&WinCertUefiGuid->CertType, &gEfiCertTypePkcs7Guid)) {
+ continue;
+ }
+ AuthData = WinCertUefiGuid->CertData;
+ AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
+
+ } else {
+ if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {
+ break;
+ }
+ continue;
+ }
+ //
+ // Verify Pkcs signed data type.
+ //
+ // At least 1 Cert from Pe Image should be in DB
+ // None of Certs should be found in DBX
+ //
+ // get Digest Algorithm, set mCertType
+ // lock mutex, preserve Pkcs7 context
+ Status = HashPeImageByType (AuthData, AuthDataSize);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Check the digital signature against the revoked certificate in forbidden database (dbx).
+ //
+ if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE1, Pkcs7CertGetMatchInCertChain)) {
+
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
+ VerifyStatus = EFI_ACCESS_DENIED;
+ break;
+ }
+ //
+ // Check the digital signature against the valid certificate in allowed database (db).
+ //
+ if (EFI_ERROR (VerifyStatus)) {
+ if(IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, Pkcs7CertValidate)) {
+
+ VerifyStatus = EFI_SUCCESS;
+ }
+ }
+ // clear context
+ Status = mDigitalSigProtocol->Pkcs7Verify (
+ mDigitalSigProtocol,
+ AuthData, AuthDataSize,
+ NULL, 0,
+ NULL, NULL,
+ Pkcs7Arg0, // Dummy op
+ RESET // Flags
+ );
+
+ } // end multi-sig for
+
+// if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size + ALIGN_SIZE(SecDataDir->Size))) {
+ if(Action != EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {
+ if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {
+ TRACE((TRACE_ALWAYS,"Offset outside of CertDir boundary %X != %x\n", OffSet, SecDataDir->VirtualAddress + SecDataDir->Size));
+ //
+ // The Size in Certificate Table or the attribute certificate table is corrupted.
+ //
+ VerifyStatus = EFI_ACCESS_DENIED;
+ } else
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND;
+ }
+
+ } // end Signed cert branch
+
+ // Image not Signed or
+ // Image is Signed, its Cert verified in db but not found in DBX
+ if(mCertType != &gEfiCertSha256Guid &&
+ Action != EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {
+
+ //
+ // This image is not signed or signed but found only in db or failed previous checks.
+ // Expected:
+ // The SHA256 hash value of the image must match a record in the security database "db",
+ // and not be reflected in the security data base "dbx".
+ //
+ TRACE((TRACE_ALWAYS,"IMAGE not Signed\n\tor signed with non-Sha256, Try Sha256 Hash Cert...\n"));
+
+ if(!HashPeImage (HASHALG_SHA256)) // init Hash type and calculate PE hash if not done already
+ goto Done;
+
+ if(IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, &gEfiCertSha256Guid, mImageDigest, mImageDigestSize)) {
+ //
+ // Image Hash in forbidden database (DBX)
+ //
+ VerifyStatus = EFI_ACCESS_DENIED;
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
+ } else
+ // no - try in allowed db if not there already
+ if(EFI_ERROR (VerifyStatus) &&
+ IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, &gEfiCertSha256Guid, mImageDigest, mImageDigestSize)) {
+ //
+ // Image Hash is in allowed database (DB).
+ //
+ VerifyStatus = EFI_SUCCESS;
+ }
+ }
+ //
+ // Signature database check after verification.
+ //
+ if(!EFI_ERROR (VerifyStatus) ) {
+ //
+ // Executable signature is found in authorized signature database.
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_ACCESS_DENIED;
+
+ if(Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {
+ //
+ // Executable signature is found in forbidden signature database.
+ //
+ TRACE((TRACE_ALWAYS,"Certificate IS FOUND in Forbidden database!\n"));
+ } else
+ //
+ // Verification failure.
+ //
+ if(Action == EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND) {
+ //
+ // Executable signature cannot be found in authorized signature database.
+ // Use platform policy to determine the action.
+ //
+ TRACE((TRACE_ALWAYS,"Certificate NOT FOUND in authorized database!\n"));
+ }
+ else
+ TRACE((TRACE_ALWAYS,"Image Certificate is Invalid!\n"));
+
+ TRACE((TRACE_ALWAYS,"%r Record added to Image Execution Table\n", Status));
+
+ if(!mCertType || !mImageDigestSize ) {
+ goto Done;
+ }
+ SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;
+
+ // Security review EIP[104046]:7. Unchecked AllocatePool may result in NULL pointer dereference
+ if (!EFI_ERROR(pBS->AllocatePool(EfiBootServicesData, SignatureListSize, &SignatureList)))
+ {
+ MemSet(SignatureList, SignatureListSize, 0);
+ SignatureList->SignatureHeaderSize = 0;
+ SignatureList->SignatureListSize = (UINT32) SignatureListSize;
+ SignatureList->SignatureSize = (UINT32) mImageDigestSize;
+ CopyMem (&SignatureList->SignatureType, mCertType, sizeof (EFI_GUID));
+ Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));
+ CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);
+ }
+ if (SignatureList != NULL) {
+ pBS->FreePool (SignatureList);
+ }
+ }
+Done:
+ if (Status != EFI_SUCCESS) {
+ //
+ // Policy decides to defer or reject the image; add its information in image executable information table.
+ //
+ AddImageExeInfo (Action, NULL, File, SignatureList, SignatureListSize);
+ // Treat unsecured images according to Image Authorization policy
+ Status = ImageAuthorization (Policy, Action);
+ }
+ if(bFileRead)
+ pBS->FreePool (FileBuffer);
+
+TRACE((TRACE_ALWAYS,"Image Verification ...%r\n", Status));
+ return Status;
+}
+
+//===================== Security Architectural Protocol ======================
+#ifndef EFI_SECURITY2_ARCH_PROTOCOL_GUID
+#define EFI_SECURITY2_ARCH_PROTOCOL_GUID \
+ { 0x94ab2f58, 0x1438, 0x4ef1, 0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0xe, 0x68 }
+
+typedef struct _EFI_SECURITY2_ARCH_PROTOCOL EFI_SECURITY2_ARCH_PROTOCOL;
+
+typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) (
+ IN CONST EFI_SECURITY2_ARCH_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
+ IN VOID *FileBuffer,
+ IN UINTN FileSize,
+ IN BOOLEAN BootPolicy
+);
+
+struct _EFI_SECURITY2_ARCH_PROTOCOL {
+ EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication;
+};
+
+static EFI_GUID gEfiSecurity2ArchProtocolGuid = EFI_SECURITY2_ARCH_PROTOCOL_GUID;
+#endif
+
+EFI_STATUS SecureFileAuthentication2(
+ IN CONST EFI_SECURITY2_ARCH_PROTOCOL *This,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *File,
+ IN VOID *FileBuffer,
+ IN UINTN FileSize,
+ IN BOOLEAN BootPolicy
+ )
+{
+ EFI_STATUS Status;
+
+ TRACE((TRACE_ALWAYS,"...............Call Security2 Arch proto.. File=%x, FileBuffer=%x, FileSize=%d\n",File,FileBuffer,FileSize ));
+
+ //
+ // skip verification if platform is NOT in SECURE BOOT MODE
+ //
+ if(mSecureBootEnable == 0)
+ return EFI_SUCCESS;
+
+ //
+ // Protocol should have been installed by AmiDigitalSig Driver once it's dispatched
+ //
+ if( mDigitalSigProtocol == NULL )
+ return EFI_ACCESS_DENIED;
+
+ Status = DxeImageVerificationHandler(File, FileBuffer, FileSize, BootPolicy);
+ // Install Tbl only on the Boot Loader launch
+ if (!EFI_ERROR (Status)/* && BootPolicy*/) {
+ AddBootImageCertInfo(NULL, mTrustSigDbOffs, mTrustSigDbSize);
+ mTrustSigDbOffs = 0;
+ mTrustSigDbSize = 0;
+ }
+ TRACE((TRACE_ALWAYS,"...............return status %r\n",Status));
+ return Status;
+}
+
+EFI_STATUS SecureFileAuthentication(
+ IN EFI_SECURITY_ARCH_PROTOCOL *This,
+ IN UINT32 AuthenticationStatus,
+ IN EFI_DEVICE_PATH_PROTOCOL *File
+ )
+{
+ BOOLEAN BootPolicy;
+ VOID *FileBuffer;
+ UINTN FileSize;
+
+ BootPolicy = TRUE;
+ FileBuffer = NULL;
+ FileSize = 0;
+
+ TRACE((TRACE_ALWAYS,".........Call Security Arch proto.. File=%x\n",File));
+
+ if (File == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ //Security Protocol w/a: BootPolicy == 1 if File->Type == 4 Media Dev Path
+// if(File->Type == 4) // Media Dev Path
+// BootPolicy=TRUE;
+
+ return SecureFileAuthentication2(NULL, File, FileBuffer, FileSize, BootPolicy);
+}
+
+EFI_SECURITY2_ARCH_PROTOCOL mSecurity2 = {SecureFileAuthentication2};
+EFI_SECURITY_ARCH_PROTOCOL mSecurity = {SecureFileAuthentication};
+
+//----------------------------------------------------------------------------
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InitDigitalProtocolCallback
+//
+// Description: This function initialize mDigitalSigProtocol ptr
+//
+//
+// Input: IN EFI_EVENT Event - Event that was triggered
+// IN VOID *Context - data pointer to information that is defined
+// when the event is registered
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS InitDigitalProtocolCallback(IN EFI_EVENT Event, IN VOID *Context)
+{
+ EFI_STATUS Status;
+ UINTN DataSize;
+ UINT8 *pSecureBootEnable=NULL;
+ //
+ // Look up for image authorization policy in "SetupData" variable
+ //
+#if (defined(ENABLE_IMAGE_EXEC_POLICY_OVERRIDE) && ENABLE_IMAGE_EXEC_POLICY_OVERRIDE == 1)
+ DataSize = sizeof(mSecureBootSetup);
+ Status = pRS->GetVariable (AMI_SECURE_BOOT_SETUP_VAR,&gSecureSetupGuid,NULL,&DataSize,&mSecureBootSetup);
+ if(EFI_ERROR(Status) ||
+ // Standard boot mode policy->apply defaults
+ mSecureBootSetup.SecureBootMode == STANDARD_SECURE_BOOT ||
+ // Policy check against fixed settings
+ mSecureBootSetup.Load_from_OROM < LOAD_FROM_OROM ||
+ mSecureBootSetup.Load_from_REMOVABLE_MEDIA < LOAD_FROM_REMOVABLE_MEDIA ||
+ mSecureBootSetup.Load_from_FIXED_MEDIA < LOAD_FROM_FIXED_MEDIA
+ )
+#endif
+ {
+ mSecureBootSetup.Load_from_OROM = LOAD_FROM_OROM;
+ mSecureBootSetup.Load_from_REMOVABLE_MEDIA = LOAD_FROM_REMOVABLE_MEDIA;
+ mSecureBootSetup.Load_from_FIXED_MEDIA = LOAD_FROM_FIXED_MEDIA;
+ }
+ //
+ // SecureBoot variable to be installed along with NVRAM driver
+ //
+ pSecureBootEnable = GetEfiGlobalVariableEx (EFI_SECURE_BOOT_NAME, &DataSize);
+ if(pSecureBootEnable && DataSize==1)
+ mSecureBootEnable = *pSecureBootEnable;
+ //
+ // will skip verification if platform is NOT in SECURE BOOT MODE
+ //
+ if(mSecureBootEnable == 0)
+ return EFI_SUCCESS;
+
+ Status = pBS->LocateHandleBuffer (
+ ByProtocol,
+ #if (PI_SPECIFICATION_VERSION < 0x00010000)
+ &gEfiFirmwareVolumeProtocolGuid,
+ #else
+ &gEfiFirmwareVolume2ProtocolGuid,
+ #endif
+ NULL,
+ &mFvHandlesCount,
+ &mFvHandles
+ );
+ if(!EFI_ERROR(Status)){
+ gImageLoadingAfterBDS = TRUE;
+ }
+
+ return pBS->LocateProtocol( &gAmiDigitalSignatureProtocolGuid, NULL, &mDigitalSigProtocol );
+}
+
+extern BOOLEAN const InstallDummySecurityProtocol;
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: InstallSecurityArchProtocol
+//
+// Description: This function installs the EFI_SECURITY_ARCH_PROTOCOL.
+// It is called at DxeCoreInitialize.
+//
+// Input:
+// EFI_HANDLE ImageHandle Image handle.
+// EFI_SYSTEM_TABLE *SystemTable Pointer to the EFI system table.
+//
+// Output:
+// EFI_SUCCESS : Security Architecture protocols are successfully installed.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID InstallSecurityArchProtocol(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_HANDLE Handle = NULL;
+ EFI_EVENT Event;
+ VOID *p;
+
+ if (InstallDummySecurityProtocol)
+ return;
+
+ // Enable Security verification at beginning of BDS connect controller phase,
+ // We assume all drivers before the event were launched from internal FV
+ // !!! This bds event is only available since core 4.6.3.5.
+ RegisterProtocolCallback(
+ &BdsConnectDriversProtocolGuid,
+ InitDigitalProtocolCallback,
+ NULL,
+ &Event,
+ &p
+ );
+ // Security2 Arch protocol must be installed before Security Arch protocol
+ pBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &gEfiSecurity2ArchProtocolGuid, &mSecurity2,
+ &gEfiSecurityArchProtocolGuid, &mSecurity,
+ NULL
+ );
+}
+
+#pragma warning (default : 4090)
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.h b/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.h
new file mode 100644
index 0000000..1a3ddd5
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/DxeImageVerificationLib.h
@@ -0,0 +1,175 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/DxeImageVerificationLib.h 3 3/15/13 4:59p Alexp $
+//
+// $Revision: 3 $
+//
+// $Date: 3/15/13 4:59p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/DxeImageVerificationLib.h $
+//
+// 3 3/15/13 4:59p Alexp
+// EIP:118243 add support for multi-signed PE Images
+//
+// 2 4/20/12 5:14p Alexp
+// Add new function to install the handle on Efi System Table with the
+// location
+// within DB variable of the Trusted Certificate that was used to verify
+// signature of Efi OS BootLoader image.
+//
+// 1 6/13/11 5:25p Alexp
+//
+// 2 5/10/11 5:05p Alexp
+// add header & footer
+//
+//
+//
+//**********************************************************************
+//
+// This file contains an 'Intel Peripheral Driver' and is
+// licensed for Intel CPUs and chipsets under the terms of your
+// license agreement with Intel or your vendor. This file may
+// be modified by the user, subject to additional terms of the
+// license agreement
+//
+/** @file
+
+ The internal header file includes the common header files, defines
+ internal structure and functions used by ImageVerificationLib.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. <BR>
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+**/
+
+#ifndef __IMAGEVERIFICATIONLIB_H__
+#define __IMAGEVERIFICATIONLIB_H__
+
+
+#include <Protocol/FirmwareVolume.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include "WinCertificate.h"
+#include <ImageAuthentication.h>
+#include <Protocol/Hash.h>
+
+#define EFI_CERT_TYPE_RSA2048_SHA256_SIZE 256
+#define EFI_CERT_TYPE_RSA2048_SIZE 256
+#define EFI_CERT_TYPE_SHA256_SIZE 32
+#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 0x00000001
+#define HASHALG_SHA256 0x00000002
+
+#define MAX_ELEM_NUM 28 // TBD. ~20 max number of PE hdr elements to be hashed in one pass
+///
+/// SHA-1 digest size in bytes.
+///
+#define SHA1_DIGEST_SIZE 20
+///
+/// SHA-256 digest size in bytes
+///
+#define SHA256_DIGEST_SIZE 32
+
+//
+// Set max digest size as SHA256 Output (32 bytes) by far
+//
+#define MAX_DIGEST_SIZE SHA256_DIGEST_SIZE
+
+#define ALIGNMENT_SIZE 8
+#define ALIGN_SIZE(a) (((a) % ALIGNMENT_SIZE) ? ALIGNMENT_SIZE - ((a) % ALIGNMENT_SIZE) : 0)
+
+#ifndef OFFSET_OF
+#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field))
+#endif
+
+//defined for every CPU architecture
+// Maximum legal IA-32 address
+#ifndef EFI_MAX_ADDRESS
+#define EFI_MAX_ADDRESS 0xFFFFFFFF
+#endif
+
+//
+//
+// PKCS7 Certificate definition
+//
+typedef struct _WIN_CERTIFICATE_EFI_PKCS {
+ WIN_CERTIFICATE Hdr;
+ UINT8 CertData[1];
+} WIN_CERTIFICATE_EFI_PKCS;
+
+//
+// Definitions for Efi System table entry to store the location within DB variable
+// of the Trusted Certificate that was used to verify Efi OS BootLoader image
+//
+//6683D10C-CF6E-4914-B5B4-AB8ED7370ED7
+#define AMI_VALID_BOOT_IMAGE_CERT_TBL_GUID \
+ { 0x6683D10C, 0xCF6E, 0x4914, 0xB5, 0xB4, 0xAB, 0x8E, 0xD7, 0x37, 0x0E, 0xD7 }
+//
+//
+// Data Table definition
+//
+typedef struct _AMI_VALID_CERT_IN_SIG_DB {
+ UINT32 SigOffset;
+ UINT32 SigLength;
+} AMI_VALID_CERT_IN_SIG_DB;
+
+#endif
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/EfiImage.h b/Core/EM/SecurityPkg/ImageVerificationLib/EfiImage.h
new file mode 100644
index 0000000..f50b0e5
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/EfiImage.h
@@ -0,0 +1,702 @@
+/*++
+
+Copyright (c) 2004 - 2006, Intel Corporation
+All rights reserved. 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.
+
+Module Name:
+
+ EfiImage.h
+
+Abstract:
+
+ EFI image format for PE32+. Please note some data structures are different
+ for IA-32 and Itanium-based images, look for UINTN and the #ifdef EFI_IA64
+
+ BugBug: Fix text - doc as defined in MSFT EFI specification
+
+--*/
+
+#ifndef _EFI_IMAGE_H_
+#define _EFI_IMAGE_H_
+
+//
+// PE32+ Subsystem type for EFI images
+//
+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10
+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
+
+//
+// BugBug: Need to get a real answer for this problem. This is not in the
+// PE specification.
+//
+// A SAL runtime driver does not get fixed up when a transition to
+// virtual mode is made. In all other cases it should be treated
+// like a EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER image
+//
+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13
+
+//
+// PE32+ Machine type for EFI images
+//
+#define EFI_IMAGE_MACHINE_IA32 0x014c
+#define EFI_IMAGE_MACHINE_IA64 0x0200
+#define EFI_IMAGE_MACHINE_X64 0x8664
+#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01c2
+
+//
+// #define EFI_IMAGE_MACHINE_FCODE 0xfc0d
+//
+#define EFI_IMAGE_MACHINE_EBC 0x0EBC
+
+#define EFI_IMAGE_DOS_SIGNATURE 0x5A4D // MZ
+#define EFI_IMAGE_OS2_SIGNATURE 0x454E // NE
+#define EFI_IMAGE_OS2_SIGNATURE_LE 0x454C // LE
+#define EFI_IMAGE_NT_SIGNATURE 0x00004550 // PE00
+#define EFI_IMAGE_EDOS_SIGNATURE 0x44454550 // PEED
+//
+// PE images can start with an optional DOS header, so if an image is run
+// under DOS it can print an error message.
+//
+typedef struct {
+ UINT16 e_magic; // Magic number
+ UINT16 e_cblp; // Bytes on last page of file
+ UINT16 e_cp; // Pages in file
+ UINT16 e_crlc; // Relocations
+ UINT16 e_cparhdr; // Size of header in paragraphs
+ UINT16 e_minalloc; // Minimum extra paragraphs needed
+ UINT16 e_maxalloc; // Maximum extra paragraphs needed
+ UINT16 e_ss; // Initial (relative) SS value
+ UINT16 e_sp; // Initial SP value
+ UINT16 e_csum; // Checksum
+ UINT16 e_ip; // Initial IP value
+ UINT16 e_cs; // Initial (relative) CS value
+ UINT16 e_lfarlc; // File address of relocation table
+ UINT16 e_ovno; // Overlay number
+ UINT16 e_res[4]; // Reserved words
+ UINT16 e_oemid; // OEM identifier (for e_oeminfo)
+ UINT16 e_oeminfo; // OEM information; e_oemid specific
+ UINT16 e_res2[10]; // Reserved words
+ UINT32 e_lfanew; // File address of new exe header
+} EFI_IMAGE_DOS_HEADER;
+
+//
+// File header format.
+//
+typedef struct {
+ UINT16 Machine;
+ UINT16 NumberOfSections;
+ UINT32 TimeDateStamp;
+ UINT32 PointerToSymbolTable;
+ UINT32 NumberOfSymbols;
+ UINT16 SizeOfOptionalHeader;
+ UINT16 Characteristics;
+} EFI_IMAGE_FILE_HEADER;
+
+#define EFI_IMAGE_SIZEOF_FILE_HEADER 20
+
+#define EFI_IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.
+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references).
+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.
+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.
+#define EFI_IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file
+#define EFI_IMAGE_FILE_SYSTEM 0x1000 // System File.
+#define EFI_IMAGE_FILE_DLL 0x2000 // File is a DLL.
+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.
+#define EFI_IMAGE_FILE_MACHINE_UNKNOWN 0
+#define EFI_IMAGE_FILE_MACHINE_I386 0x14c // Intel 386.
+#define EFI_IMAGE_FILE_MACHINE_R3000 0x162 // MIPS* little-endian, 0540 big-endian
+#define EFI_IMAGE_FILE_MACHINE_R4000 0x166 // MIPS* little-endian
+#define EFI_IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP*
+#define EFI_IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM* PowerPC Little-Endian
+#define EFI_IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine
+//
+// * Other names and brands may be claimed as the property of others.
+//
+//
+// Directory format.
+//
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 Size;
+} EFI_IMAGE_DATA_DIRECTORY;
+
+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
+
+typedef struct {
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData;
+ UINT32 BaseOfBss;
+ UINT32 GprMask;
+ UINT32 CprMask[4];
+ UINT32 GpValue;
+} EFI_IMAGE_ROM_OPTIONAL_HEADER;
+
+#define EFI_IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
+#define EFI_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER sizeof (EFI_IMAGE_ROM_OPTIONAL_HEADER)
+
+typedef struct {
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader;
+} EFI_IMAGE_ROM_HEADERS;
+
+//
+// ATTENTION!!! EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64
+// are for use ONLY by tools. All proper EFI code MUST use
+// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!
+//
+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
+
+typedef struct {
+ //
+ // Standard fields.
+ //
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ UINT32 BaseOfData;
+ //
+ // NT additional fields.
+ //
+ UINT32 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT32 SizeOfStackReserve;
+ UINT32 SizeOfStackCommit;
+ UINT32 SizeOfHeapReserve;
+ UINT32 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER32;
+
+//
+// ATTENTION!!! EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64
+// are for use ONLY by tools. All proper EFI code MUST use
+// EFI_IMAGE_OPTIONAL_HEADER ONLY!!!
+//
+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
+
+typedef struct {
+ //
+ // Standard fields.
+ //
+ UINT16 Magic;
+ UINT8 MajorLinkerVersion;
+ UINT8 MinorLinkerVersion;
+ UINT32 SizeOfCode;
+ UINT32 SizeOfInitializedData;
+ UINT32 SizeOfUninitializedData;
+ UINT32 AddressOfEntryPoint;
+ UINT32 BaseOfCode;
+ //
+ // NT additional fields.
+ //
+ UINT64 ImageBase;
+ UINT32 SectionAlignment;
+ UINT32 FileAlignment;
+ UINT16 MajorOperatingSystemVersion;
+ UINT16 MinorOperatingSystemVersion;
+ UINT16 MajorImageVersion;
+ UINT16 MinorImageVersion;
+ UINT16 MajorSubsystemVersion;
+ UINT16 MinorSubsystemVersion;
+ UINT32 Win32VersionValue;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfHeaders;
+ UINT32 CheckSum;
+ UINT16 Subsystem;
+ UINT16 DllCharacteristics;
+ UINT64 SizeOfStackReserve;
+ UINT64 SizeOfStackCommit;
+ UINT64 SizeOfHeapReserve;
+ UINT64 SizeOfHeapCommit;
+ UINT32 LoaderFlags;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
+} EFI_IMAGE_OPTIONAL_HEADER64;
+
+//
+// ATTENTION!!! EFI_IMAGE_NT_HEADERS32 and EFI_IMAGE_HEADERS64 are for use ONLY
+// by tools. All proper EFI code MUST use EFI_IMAGE_NT_HEADERS ONLY!!!
+//
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS32;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)
+
+typedef struct {
+ UINT32 Signature;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;
+} EFI_IMAGE_NT_HEADERS64;
+
+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)
+
+//
+// Include processor specific definition of EFI_IMAGE_OPTIONAL_HEADER so the
+// type name EFI_IMAGE_OPTIONAL_HEADER is appropriate to the build. Same for
+// EFI_IMAGE_NT_HEADERS. These definitions MUST be used by ALL EFI code.
+//
+#if !defined(EFI64) && !defined(EFIx64)
+//IA32
+#define EFI_IMAGE_MACHINE_TYPE (EFI_IMAGE_MACHINE_IA32)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_X64)
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+typedef EFI_IMAGE_OPTIONAL_HEADER32 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS32 EFI_IMAGE_NT_HEADERS;
+#elif defined(EFI64)
+//IPF
+#define EFI_IMAGE_MACHINE_TYPE (EFI_IMAGE_MACHINE_IA64)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_IA64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
+
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS;
+#elif defined(EFIx64)
+//x64
+#define EFI_IMAGE_MACHINE_TYPE (EFI_IMAGE_MACHINE_X64)
+
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
+ (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC))
+
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_IA32)
+
+//
+// Assume we can use IPF values
+//
+#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
+typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER;
+typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS;
+#endif
+
+#define EFI_IMAGE_FIRST_SECTION(ntheader) \
+ ( \
+ (EFI_IMAGE_SECTION_HEADER *) \
+ ( \
+ (UINT32) ntheader + \
+ FIELD_OFFSET (EFI_IMAGE_NT_HEADERS, OptionalHeader) + \
+ ((EFI_IMAGE_NT_HEADERS *) (ntheader))->FileHeader.SizeOfOptionalHeader \
+ ) \
+ )
+
+//
+// Subsystem Values
+//
+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0
+#define EFI_IMAGE_SUBSYSTEM_NATIVE 1
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3.
+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5
+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7
+
+//
+// Directory Entries
+//
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0
+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1
+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2
+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4
+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5
+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6
+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9
+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
+
+//
+// Section header format.
+//
+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
+
+typedef struct {
+ UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ UINT32 PhysicalAddress;
+ UINT32 VirtualSize;
+ } Misc;
+ UINT32 VirtualAddress;
+ UINT32 SizeOfRawData;
+ UINT32 PointerToRawData;
+ UINT32 PointerToRelocations;
+ UINT32 PointerToLinenumbers;
+ UINT16 NumberOfRelocations;
+ UINT16 NumberOfLinenumbers;
+ UINT32 Characteristics;
+} EFI_IMAGE_SECTION_HEADER;
+
+#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40
+
+#define EFI_IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved.
+#define EFI_IMAGE_SCN_CNT_CODE 0x00000020
+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
+
+#define EFI_IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved.
+#define EFI_IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information.
+#define EFI_IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.
+#define EFI_IMAGE_SCN_LNK_COMDAT 0x00001000
+
+#define EFI_IMAGE_SCN_ALIGN_1BYTES 0x00100000
+#define EFI_IMAGE_SCN_ALIGN_2BYTES 0x00200000
+#define EFI_IMAGE_SCN_ALIGN_4BYTES 0x00300000
+#define EFI_IMAGE_SCN_ALIGN_8BYTES 0x00400000
+#define EFI_IMAGE_SCN_ALIGN_16BYTES 0x00500000
+#define EFI_IMAGE_SCN_ALIGN_32BYTES 0x00600000
+#define EFI_IMAGE_SCN_ALIGN_64BYTES 0x00700000
+
+#define EFI_IMAGE_SCN_MEM_DISCARDABLE 0x02000000
+#define EFI_IMAGE_SCN_MEM_NOT_CACHED 0x04000000
+#define EFI_IMAGE_SCN_MEM_NOT_PAGED 0x08000000
+#define EFI_IMAGE_SCN_MEM_SHARED 0x10000000
+#define EFI_IMAGE_SCN_MEM_EXECUTE 0x20000000
+#define EFI_IMAGE_SCN_MEM_READ 0x40000000
+#define EFI_IMAGE_SCN_MEM_WRITE 0x80000000
+
+//
+// Symbol format.
+//
+#define EFI_IMAGE_SIZEOF_SYMBOL 18
+
+//
+// Section values.
+//
+// Symbols have a section number of the section in which they are
+// defined. Otherwise, section numbers have the following meanings:
+//
+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 // Symbol is undefined or is common.
+#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 // Symbol is an absolute value.
+#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 // Symbol is a special debug item.
+//
+// Type (fundamental) values.
+//
+#define EFI_IMAGE_SYM_TYPE_NULL 0 // no type.
+#define EFI_IMAGE_SYM_TYPE_VOID 1 //
+#define EFI_IMAGE_SYM_TYPE_CHAR 2 // type character.
+#define EFI_IMAGE_SYM_TYPE_SHORT 3 // type short integer.
+#define EFI_IMAGE_SYM_TYPE_INT 4
+#define EFI_IMAGE_SYM_TYPE_LONG 5
+#define EFI_IMAGE_SYM_TYPE_FLOAT 6
+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
+#define EFI_IMAGE_SYM_TYPE_STRUCT 8
+#define EFI_IMAGE_SYM_TYPE_UNION 9
+#define EFI_IMAGE_SYM_TYPE_ENUM 10 // enumeration.
+#define EFI_IMAGE_SYM_TYPE_MOE 11 // member of enumeration.
+#define EFI_IMAGE_SYM_TYPE_BYTE 12
+#define EFI_IMAGE_SYM_TYPE_WORD 13
+#define EFI_IMAGE_SYM_TYPE_UINT 14
+#define EFI_IMAGE_SYM_TYPE_DWORD 15
+
+//
+// Type (derived) values.
+//
+#define EFI_IMAGE_SYM_DTYPE_NULL 0 // no derived type.
+#define EFI_IMAGE_SYM_DTYPE_POINTER 1
+#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2
+#define EFI_IMAGE_SYM_DTYPE_ARRAY 3
+
+//
+// Storage classes.
+//
+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION (UINT8) -1
+#define EFI_IMAGE_SYM_CLASS_NULL 0
+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2
+#define EFI_IMAGE_SYM_CLASS_STATIC 3
+#define EFI_IMAGE_SYM_CLASS_REGISTER 4
+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5
+#define EFI_IMAGE_SYM_CLASS_LABEL 6
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
+#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9
+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
+#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12
+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13
+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15
+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17
+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18
+#define EFI_IMAGE_SYM_CLASS_BLOCK 100
+#define EFI_IMAGE_SYM_CLASS_FUNCTION 101
+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102
+#define EFI_IMAGE_SYM_CLASS_FILE 103
+#define EFI_IMAGE_SYM_CLASS_SECTION 104
+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
+
+//
+// type packing constants
+//
+#define EFI_IMAGE_N_BTMASK 017
+#define EFI_IMAGE_N_TMASK 060
+#define EFI_IMAGE_N_TMASK1 0300
+#define EFI_IMAGE_N_TMASK2 0360
+#define EFI_IMAGE_N_BTSHFT 4
+#define EFI_IMAGE_N_TSHIFT 2
+
+//
+// Communal selection types.
+//
+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1
+#define EFI_IMAGE_COMDAT_SELECT_ANY 2
+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3
+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4
+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
+
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
+
+//
+// Relocation format.
+//
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SymbolTableIndex;
+ UINT16 Type;
+} EFI_IMAGE_RELOCATION;
+
+#define EFI_IMAGE_SIZEOF_RELOCATION 10
+
+//
+// I386 relocation types.
+//
+#define EFI_IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary
+#define EFI_IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address
+#define EFI_IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included
+#define EFI_IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address
+#define EFI_IMAGE_REL_I386_SECTION 012
+#define EFI_IMAGE_REL_I386_SECREL 013
+#define EFI_IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address
+//
+// Based relocation format.
+//
+typedef struct {
+ UINT32 VirtualAddress;
+ UINT32 SizeOfBlock;
+} EFI_IMAGE_BASE_RELOCATION;
+
+#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8
+
+//
+// Based relocation types.
+//
+#define EFI_IMAGE_REL_BASED_ABSOLUTE 0
+#define EFI_IMAGE_REL_BASED_HIGH 1
+#define EFI_IMAGE_REL_BASED_LOW 2
+#define EFI_IMAGE_REL_BASED_HIGHLOW 3
+#define EFI_IMAGE_REL_BASED_HIGHADJ 4
+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5
+#define EFI_IMAGE_REL_BASED_IA64_IMM64 9
+#define EFI_IMAGE_REL_BASED_DIR64 10
+
+//
+// Line number format.
+//
+typedef struct {
+ union {
+ UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0.
+ UINT32 VirtualAddress; // Virtual address of line number.
+ } Type;
+ UINT16 Linenumber; // Line number.
+} EFI_IMAGE_LINENUMBER;
+
+#define EFI_IMAGE_SIZEOF_LINENUMBER 6
+
+//
+// Archive format.
+//
+#define EFI_IMAGE_ARCHIVE_START_SIZE 8
+#define EFI_IMAGE_ARCHIVE_START "!<arch>\n"
+#define EFI_IMAGE_ARCHIVE_END "`\n"
+#define EFI_IMAGE_ARCHIVE_PAD "\n"
+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ "
+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
+
+typedef struct {
+ UINT8 Name[16]; // File member name - `/' terminated.
+ UINT8 Date[12]; // File member date - decimal.
+ UINT8 UserID[6]; // File member user id - decimal.
+ UINT8 GroupID[6]; // File member group id - decimal.
+ UINT8 Mode[8]; // File member mode - octal.
+ UINT8 Size[10]; // File member size - decimal.
+ UINT8 EndHeader[2]; // String to end header.
+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
+
+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
+
+//
+// DLL support.
+//
+//
+// Export Format
+//
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Name;
+ UINT32 Base;
+ UINT32 NumberOfFunctions;
+ UINT32 NumberOfNames;
+ UINT32 AddressOfFunctions;
+ UINT32 AddressOfNames;
+ UINT32 AddressOfNameOrdinals;
+} EFI_IMAGE_EXPORT_DIRECTORY;
+
+//
+// Import Format
+//
+typedef struct {
+ UINT16 Hint;
+ UINT8 Name[1];
+} EFI_IMAGE_IMPORT_BY_NAME;
+
+typedef struct {
+ union {
+ UINT32 Function;
+ UINT32 Ordinal;
+ EFI_IMAGE_IMPORT_BY_NAME *AddressOfData;
+ } u1;
+} EFI_IMAGE_THUNK_DATA;
+
+#define EFI_IMAGE_ORDINAL_FLAG 0x80000000
+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
+#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT32 ForwarderChain;
+ UINT32 Name;
+ EFI_IMAGE_THUNK_DATA *FirstThunk;
+} EFI_IMAGE_IMPORT_DESCRIPTOR;
+
+//
+// Debug Format
+//
+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2
+
+typedef struct {
+ UINT32 Characteristics;
+ UINT32 TimeDateStamp;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT32 Type;
+ UINT32 SizeOfData;
+ UINT32 RVA;
+ UINT32 FileOffset;
+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
+
+#define CODEVIEW_SIGNATURE_NB10 0x3031424E // "NB10"
+typedef struct {
+ UINT32 Signature; // "NB10"
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
+
+#define CODEVIEW_SIGNATURE_RSDS 0x53445352 // "RSDS"
+typedef struct {
+ UINT32 Signature; // "RSDS"
+ UINT32 Unknown;
+ UINT32 Unknown2;
+ UINT32 Unknown3;
+ UINT32 Unknown4;
+ UINT32 Unknown5;
+ //
+ // Filename of .PDB goes here
+ //
+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
+
+//
+// Header format for TE images
+//
+typedef struct {
+ UINT16 Signature; // signature for TE format = "VZ"
+ UINT16 Machine; // from the original file header
+ UINT8 NumberOfSections; // from the original file header
+ UINT8 Subsystem; // from original optional header
+ UINT16 StrippedSize; // how many bytes we removed from the header
+ UINT32 AddressOfEntryPoint; // offset to entry point -- from original optional header
+ UINT32 BaseOfCode; // from original image -- required for ITP debug
+ UINT64 ImageBase; // from original file header
+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; // only base relocation and debug directory
+} EFI_TE_IMAGE_HEADER;
+
+#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56 // "VZ"
+//
+// Data directory indexes in our TE image header
+//
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0
+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1
+
+//
+// Union of PE32, PE32+, and TE headers
+//
+typedef union {
+ EFI_IMAGE_NT_HEADERS32 Pe32;
+ EFI_IMAGE_NT_HEADERS64 Pe32Plus;
+ EFI_TE_IMAGE_HEADER Te;
+} EFI_IMAGE_OPTIONAL_HEADER_UNION;
+
+typedef union {
+ EFI_IMAGE_NT_HEADERS32 *Pe32;
+ EFI_IMAGE_NT_HEADERS64 *Pe32Plus;
+ EFI_TE_IMAGE_HEADER *Te;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *Union;
+} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
+
+#endif
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.cif b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.cif
new file mode 100644
index 0000000..ff5909a
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "Image Verification Library"
+ category = ModulePart
+ LocalRoot = "Core\EM\SecurityPkg\ImageVerificationLib"
+ RefName = "ImageVerificationLib"
+[files]
+"ImageVerificationLib.sdl"
+"ImageVerificationLib.mak"
+"DxeImageVerificationLib.c"
+"DxeImageVerificationLib.h"
+"EfiImage.h"
+<endComponent>
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.mak b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.mak
new file mode 100644
index 0000000..bb6b02b
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.mak
@@ -0,0 +1,92 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2008, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#*************************************************************************
+# $Header: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/ImageVerificationLib.mak 5 8/15/13 11:28a Alexp $
+#
+# $Revision: 5 $
+#
+# $Date: 8/15/13 11:28a $
+#*************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SecureBoot_WIN8/ImageVerification_efi/ImageVerificationLib.mak $
+#
+# 5 8/15/13 11:28a Alexp
+#
+# 4 11/19/12 4:42p Alexp
+# Fix for Win8 SecureBoot logo requirement: restore Secure Boot state
+# across flash updates.
+# Move all secure boot Setup settings to a separate varsore variable.
+# Preserve var across re-flash
+#
+# 3 6/30/11 4:01p Alexp
+# moved Setup Page defines to parent SecureBoot module
+#
+# 2 6/15/11 3:06p Alexp
+# removed commented instructions
+#
+# 1 6/13/11 5:25p Alexp
+#
+# 5 5/17/11 5:35p Alexp
+#
+#
+# 3 5/11/11 1:03p Alexp
+# update file hdr
+#
+# 2 5/10/11 12:35p Alexp
+#
+# 1 5/09/11 10:04a Alexp
+#
+# 3 5/04/11 7:15p Alexp
+# add Setup controls on Secure page
+#
+# 2 4/11/11 12:58p Alexp
+# remove Crypto lib linkage
+#
+# 1 3/12/11 11:31a Alexp
+#
+# 1 3/10/11 5:00p Alexp
+#
+# 1 3/03/11 6:35p Alexp
+#
+#*************************************************************************
+#<AMI_FHDR_START>
+#
+# Name: ImageVerificationLib.mak
+#
+# Description: installs Security Architecture Protocol
+#
+#
+#<AMI_FHDR_END>
+#*************************************************************************
+CORE_DXE_LIBBin : $(IMAGEVERIFY_LIB)
+
+$(IMAGEVERIFY_LIB) : $(BUILD_DIR)\ImageVerificationLib.mak ImageVerificationLibBin
+
+$(BUILD_DIR)\ImageVerificationLib.mak : $(ImageVerificationLib_DIR)\ImageVerificationLib.cif $(BUILD_RULES)
+ $(CIF2MAK) $(ImageVerificationLib_DIR)\ImageVerificationLib.cif $(CIF2MAK_DEFAULTS)
+
+ImageVerificationLib_INCLUDES= \
+ /I $(ImageVerificationLib_DIR) \
+ /I $(SecureBoot_DIR) \
+ /I $(CORE_DIR)
+
+ImageVerificationLibBin : $(CRYPTOLIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\ImageVerificationLib.mak all\
+ NAME=ImageVerificationLib\
+ MAKEFILE=$(BUILD_DIR)\ImageVerificationLib.mak\
+ "MY_INCLUDES= $(ImageVerificationLib_INCLUDES)" \
+ TYPE=LIBRARY
diff --git a/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.sdl b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.sdl
new file mode 100644
index 0000000..73e98c0
--- /dev/null
+++ b/Core/EM/SecurityPkg/ImageVerificationLib/ImageVerificationLib.sdl
@@ -0,0 +1,109 @@
+TOKEN
+ Name = "ImageVerification_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Crypto library support in Project"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "ENABLE_IMAGE_EXEC_POLICY_OVERRIDE"
+ Value = "0"
+ Help = "Enable user override of Image Execution policy"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "ENABLE_IMAGE_EXEC_POLICY_OVERRIDE"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "DEBUG_MODE" "=" "1"
+End
+
+TOKEN
+ Name = "LOAD_FROM_FV"
+ Value = "0"
+ Help = "Load image from Internal FV. Possible options:\0-ALWAYS_EXECUTE; 1-NEVER_EXECUTE; 2-ALLOW_EXECUTE_ON_SECURITY_VIOLATION;\3-DEFER_EXECUTE_ON_SECURITY_VIOLATION; 4-DENY_EXECUTE_ON_SECURITY_VIOLATION; 5-QUERY_USER_ON_SECURITY_VIOLATION"
+ TokenType = Integer
+ TargetH = Yes
+ Lock = Yes
+ Range = "Supported options: 0"
+End
+
+TOKEN
+ Name = "LOAD_FROM_OROM"
+ Value = "4"
+ Help = "Load image from Option ROM"
+ TokenType = Integer
+ TargetH = Yes
+ Range = "Supported options: 3,4,5"
+End
+
+TOKEN
+ Name = "LOAD_FROM_REMOVABLE_MEDIA"
+ Value = "4"
+ Help = "Load image from Removable Media"
+ TokenType = Integer
+ TargetH = Yes
+ Range = "Supported options: 3,4,5"
+End
+
+TOKEN
+ Name = "LOAD_FROM_FIXED_MEDIA"
+ Value = "4"
+ Help = "Load image from Fixed Media"
+ TokenType = Integer
+ TargetH = Yes
+ Range = "Supported options: 3,4,5"
+End
+
+TOKEN
+ Name = "INSTALL_DUMMY_SECURITY_PROTOCOL"
+ Value = "0"
+ Help = "When this token is 'on', the Core publishes dummy instance of the security protocol.\The security protocol is one of the architectural protocols and as such must be available.\The default value is 'on'. \Set to 'off' if project includes driver that publishes the security protocol.\"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "LOAD_UNSIGNED_EMBEDDED_SHELL"
+ Value = "0"
+ Help = "Load Shell from Internal FV"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "LOAD_UNSIGNED_EMBEDDED_SHELL"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "DEBUG_MODE" "=" "1"
+End
+
+TOKEN
+ Name = "IMAGEVERIFY_LIB"
+ Value = "$$(LIB_BUILD_DIR)\ImageVerificationLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "ImageVerificationLib_DIR"
+ Help = "Path to Crypto library Module in Project"
+End
+
+MODULE
+ Help = "Includes ImageVerificationLib.mak to Project"
+ File = "ImageVerificationLib.mak"
+End
+
+ELINK
+ Name = "InstallSecurityArchProtocol,"
+ Parent = "DxeCoreInitialize"
+ InvokeOrder = AfterParent
+End