summaryrefslogtreecommitdiff
path: root/Core/EM/SecurityPkg/SecSMIFlash/VerifyFwCapsule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/SecurityPkg/SecSMIFlash/VerifyFwCapsule.c')
-rw-r--r--Core/EM/SecurityPkg/SecSMIFlash/VerifyFwCapsule.c790
1 files changed, 790 insertions, 0 deletions
diff --git a/Core/EM/SecurityPkg/SecSMIFlash/VerifyFwCapsule.c b/Core/EM/SecurityPkg/SecSMIFlash/VerifyFwCapsule.c
new file mode 100644
index 0000000..b078df2
--- /dev/null
+++ b/Core/EM/SecurityPkg/SecSMIFlash/VerifyFwCapsule.c
@@ -0,0 +1,790 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SecureFlashPkg/SecureSmiFlash/VerifyFwCapsule.c 30 7/03/14 10:15a Alexp $
+//
+// $Revision: 30 $
+//
+// $Date: 7/03/14 10:15a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SecureFlashPkg/SecureSmiFlash/VerifyFwCapsule.c $
+//
+// 30 7/03/14 10:15a Alexp
+// EIP176297: Fix bug in condition expresison inside For loops.
+//
+// 29 5/20/14 5:22p Alexp
+// Replace a var name gRomFileSize to a more appropriate gFwCapMaxSize
+//
+// 27 3/20/14 12:31p Alexp
+// 1. Don't re-read FwKey. Use gpPubKeyHndl
+// 2. CapsuleValidate: sanity check: FwCapHdr RomImageOffset checked
+// against max size
+// (FWCAPSULE_IMAGE_SIZE-FLASH_SIZE)
+// 3. CapsuleValidate: add parameter check pFWCapsuleHdr != NULL
+//
+// 26 8/22/13 11:34a Alexp
+// VerifyFwCertRsa2048Sha256() - Break a loop after RootCert Verify if key
+// match is found. Old code would cycle through all certs.
+//
+// 25 8/12/13 4:31p Alexp
+// add check for end of Certificate block marker
+//
+// 24 7/11/13 3:41p Alexp
+// Removed check for FWCAPSULE_MAX_HDR_SIZE. Replaced it with fixed 0x8000
+// value
+//
+// 23 6/27/13 9:43a Alexp
+// fixed range check in ROM_MAP table processing.
+//
+// 22 6/21/13 11:00a Alexp
+// HashFwRomMapImage(): add check for address overflow in UIN32 build mode
+//
+// 21 6/12/13 3:51p Alexp
+// 1. CapsuleValidate() made external function in SecSmiFlash API
+// EIP#125800 : Privilege escalation into SMM via Secure SMI Flash SMM
+// driver via GetFlUpdPolicy and SetFlUpdMethod - BugID 305294
+// add IsAddressInSmram() checks inside exposed API functions
+// 2. VerifyFwCertRsa2048Sha256() - parse multiple chained RootKey
+// certificate structures in FwCert header
+//
+// 20 12/17/12 2:51p Alexp
+// fix cppcheck style check finds
+//
+// 19 11/21/12 10:44a Alexp
+// EIP#105015: Implemented handling of Pkcs7# Certificate in Aptio Fw
+// Capsule update packages
+// Replace direct calls to Hash() infrom CryptoLib with calls to Crypto
+// API. Saves ROM space
+//
+//
+// 18 11/20/12 3:30p Alexp
+// EIP[104046]: Findings from Security review on Aptio4 Image verification
+// Includes the fix for item #10: hardening of RomMap parsing oin
+// FwCapsule update
+//
+// 17 11/13/12 3:23p Alexp
+// 1. EIP#106359 : Secure Flash Cross function fail.
+// Move FwCapSectionGuid define outside of #if branch
+// 2. Calculate offset to RomLayout table within FwCapsHdr instead of
+// using hardwired location. Pkcs#7
+// cert will differ in size and offset may change
+// 3. Remove dependency on FWSIG_SIGNHDR flag. Use Capsule flags instead.
+//
+// 16 9/18/12 6:59p Alexp
+// Bug: Recovery update was broken for FwCapsule with embedded signature
+// and FwSig_hdr token 0.
+// Fix: FindCapHdrFFS() change Ffs Hdr size testing
+//
+// 15 9/06/12 7:28p Alexp
+// Add new IGNORE_RUNTIME_UPDATE_IMAGE_REVISION_CHECK flag
+// When set, FW Capsule Validate logic will skip image Revision check only
+// for Runtime updates
+//
+// 14 7/26/12 3:26p Alexp
+// replaced #if FWSIG_PADDING == 0 with #if FWSIG_SIGNHDR == 1.
+// Flag in the FwCap Hdr to switch between PKCS1_5 and PSS padding is
+// available only if #if FWSIG_SIGNHDR == 1
+//
+// 13 5/21/12 4:55p Alexp
+// keep a pointer to FwCaps Hdr withing Capsule image. Streamlines
+// creation of Capsule Mailbox.
+//
+// 12 5/18/12 5:14p Alexp
+// 1. Add support for Embedded FwSignature file
+// 2. EIP:89687 Replace Hash PPI calls with calls to Crypto lib
+// functions.
+// Allows to support RomMap tables in FwCaps Hdr with unlimited
+// number of
+// entries
+// 3. VerifyFwVersion.
+// a) Moved the call after Rom image signature is verified.;
+// b) search $FID struct only in signed FVs with PEI or DXE
+// attributes
+//
+// 11 4/25/12 2:11p Alexp
+// Platform FW Key is compared with either Signing or if no match - with
+// RootKey certificates
+//
+// 9 3/09/12 11:16a Alexp
+// VerifyFwImage-> fixed logic to process RomMap entries.
+// Number of signed elements in RomMap may not exceed max_num_elem
+// constant.
+// Overall number of elements in th RomMap may not exceed max_num_elem x 2
+//
+// 8 2/29/12 4:13p Alexp
+// Update format of Capsule signing:
+// 1. Entire Cap Hdr and FW_Cert Hdr are included in SigCert Signature
+// calculation. Improves Cap image security
+// 2. RootKey signs only SignKey buffer and not entire Sign Certificate.
+// No need for resigning of RootCert each time SignCert is being created
+//
+// 7 2/13/12 1:57p Alexp
+// GetFidData: Use 1 byte alligned pointer in searching "Section Guid".
+// Fixes the issue with RomMap entries that are not 4 byte alligned
+//
+// 6 12/29/11 4:00p Alexp
+// VerifyProjectId().
+// Calculate size of ProjectId string based on SDL Token PROJECT_TAG
+//
+// 5 11/30/11 8:04p Alexp
+// FW Revision searched inside FID structure. Simplified the search
+// throughout FW block by 4byte aligned $FID signature only
+//
+// 4 10/17/11 11:26a Alexp
+// Fix misspelled FidSignature name
+//
+// 3 9/29/11 3:27p Alexp
+// Bug fix. EIP#71244: No Rollback support
+//
+// 2 8/05/11 3:29p Alexp
+// add SDL condition to IGNORE_IMAGE_ROLLBACK. Disabled by default
+//
+// 4 5/16/11 5:54p Alexp
+// Use 5 characters for Project Tag comparison (old was 4)
+//
+// 3 5/10/11 5:09p Alexp
+// Hash guids are defined globally
+//
+// 2 4/13/11 7:15p Alexp
+// included first draft of VersionControl code
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: VerifyFwCapsule.c
+//
+// Description: Verify Aptio FW capsule integrity and performs other security checks
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <AmiDxeLib.h>
+#include <Protocol\SmiFlash.h>
+#include <Protocol\SecSmiFlash.h>
+#include <Ppi\FwVersion.h>
+#include <RomLayout.h>
+#include <Ffs.h>
+#include "AmiCertificate.h"
+
+//----------------------------------------------------------------------------
+// Function Externs
+extern AMI_DIGITAL_SIGNATURE_PROTOCOL *gAmiSig;
+extern UINTN gFwCapMaxSize; // add 4k for capsule's header
+extern EFI_GUID gFWCapsuleGuid;
+extern EFI_GUID gPRKeyGuid;
+extern EFI_GUID gFwCapFfsGuid;
+extern EFI_SHA256_HASH *gHashTbl;
+extern CRYPT_HANDLE gpPubKeyHndl;
+extern UINT8 gHashDB[SHA256_DIGEST_SIZE];
+
+BOOLEAN IsAddressInSmram (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+);
+//----------------------------------------------------------------------------
+// Local prototypes
+EFI_STATUS CapsuleValidate (
+ IN OUT UINT8 **pFwCapsule,
+ IN OUT APTIO_FW_CAPSULE_HEADER **pFWCapsuleHdr
+);
+
+typedef struct {
+ EFI_FFS_FILE_HEADER FfsHdr;
+ EFI_COMMON_SECTION_HEADER SecHdr;
+ EFI_GUID SectionGuid;
+ UINT8 FwCapHdr[0];
+} AMI_FFS_COMMON_SECTION_HEADER;
+
+//----------------------------------------------------------------------------
+// Local Variables
+
+static EFI_GUID FwCapSectionGuid = AMI_FW_CAPSULE_SECTION_GUID;
+
+//----------------------------------------------------------------------------
+#if IGNORE_RUNTIME_UPDATE_IMAGE_REVISION_CHECK == 0
+//----------------------------------------------------------------------------
+typedef struct _FID_SECTION {
+ EFI_GUID Guid;
+ FW_VERSION FwVersion;
+} FID_SECTION;
+
+static EFI_GUID FidSectionGuid = \
+ { 0x2EBE0275, 0x6458, 0x4AF9, 0x91, 0xed, 0xD3, 0xF4, 0xED, 0xB1, 0x00, 0xAA };
+
+const UINT8 *FidSignature = "$FID";
+//----------------------------------------------------------------------------
+// Function Definitions
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: VerifyProjectId
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+VerifyProjectId (
+ IN FW_VERSION *FwVersionData
+)
+{
+ char *strProjectId = CONVERT_TO_STRING(PROJECT_TAG);
+ UINTN Size = sizeof(CONVERT_TO_STRING(PROJECT_TAG));
+/*
+CHAR8 BiosTag[9]; //BIOS Tag
+EFI_GUID FirmwareGuid; //Firmware GUID
+CHAR8 CoreMajorVersion[3];
+CHAR8 CoreMinorVersion[3];
+CHAR8 ProjectMajorVersion[3];
+CHAR8 ProjectMinorVersion[3];
+*/
+// Project ID, Major, Minor rev
+ TRACE((-1, "OrgBiosTag=%s,NewBiosTag=%s\nPrjMajVer=%02X, NewMajVer=%s\nPrjMinorVer=%02X, NewMinorVer=%s\n",
+ FwVersionData->BiosTag, strProjectId,
+ PROJECT_MAJOR_VERSION, FwVersionData->ProjectMajorVersion,
+ PROJECT_MINOR_VERSION, FwVersionData->ProjectMinorVersion
+ ));
+
+ if (Size==0 || MemCmp (FwVersionData->BiosTag, strProjectId, Size-1)) return FALSE;
+#if IGNORE_IMAGE_ROLLBACK == 0
+ if(Atoi(FwVersionData->ProjectMajorVersion) < PROJECT_MAJOR_VERSION) return FALSE;
+ if(Atoi(FwVersionData->ProjectMinorVersion) < PROJECT_MINOR_VERSION) return FALSE;
+#endif
+
+ return TRUE;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetFidData
+//
+// Description: Function to read FFS FID data structure from the given data buffer
+//
+// Input: OUT FW_VERSION **Fid - pointer to output buffer
+// IN VOID *pFV - pointer to data buffer to read from
+
+//
+// Output: EFI_SUCCESS if FID data is retrieved
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN GetFidData(
+ IN VOID *pFV,
+ IN UINT32 Size,
+ OUT FW_VERSION **FwVersionData
+)
+{
+// UINT32 Signature;
+ UINT8 *SearchPointer;
+ FID_SECTION *Section;
+
+// Simplified search by $FID signature only.
+// SearchPointer = (UINT32 *)((UINT8 *)pFV + sizeof(EFI_GUID));
+// Signature = FidSectionGuid.Data1;
+ SearchPointer = (UINT8 *)pFV;
+
+ do {
+// if(*SearchPointer == Signature) {
+ Section = (FID_SECTION *)SearchPointer;
+ if(!guidcmp(&FidSectionGuid, &(Section->Guid)) &&
+ (*((UINT32*)(&Section->FwVersion.FirmwareID[0])) == *(UINT32*)FidSignature)){
+ *FwVersionData = &Section->FwVersion;
+ return TRUE;
+ }
+// }
+ } while( SearchPointer++ < (UINT8*)((UINT32)pFV+Size));
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VerifyFwRevision
+//
+// Description: Verify Fw revision compatibility
+// NewVer > OldVer, newProjectTAGid = oldProjectTAGid
+//
+// Input:
+// IN OUT UINT8 *pCapsule
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+VerifyFwRevision (
+ IN APTIO_FW_CAPSULE_HEADER *FWCapsuleHdr,
+ IN UINT8 *RomData
+)
+{
+ ROM_AREA *Area;
+ EFI_PHYSICAL_ADDRESS FvAddress;
+ FW_VERSION *FwVersionData;
+
+ Area = (ROM_AREA *)(UINTN)((UINT32)FWCapsuleHdr+FWCapsuleHdr->RomLayoutOffset);
+
+ for (Area; Area->Size != 0; Area++) {
+ if (!(Area->Attributes & ROM_AREA_FV_SIGNED))
+ continue;
+ // $FID can be in FV with either PEI or DXE
+ if (!(Area->Attributes & (ROM_AREA_FV_PEI+ROM_AREA_FV_DXE)))
+ continue;
+
+ FvAddress = (EFI_PHYSICAL_ADDRESS)RomData + (Area->Offset);
+ if (GetFidData((UINT8*)FvAddress, Area->Size, &FwVersionData)) {
+ if(VerifyProjectId(FwVersionData))
+ return EFI_SUCCESS;
+ break;
+ }
+ }
+// At least one FW block must be signed OR no $FID structure found in the new FW image
+ return EFI_SECURITY_VIOLATION;
+}
+
+#endif // #if IGNORE_RUNTIME_UPDATE_IMAGE_REVISION_CHECK == 0
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindCapHdrFFS
+//
+// Description: Function to read FW Cap Sig data from Ffs
+//
+// Input: OUT UINT8 **pFwCapHdr - pointer to output buffer
+// IN VOID *pCapsule - pointer to data buffer to read from
+//
+// Output: EFI_SUCCESS if Capsule Hdr with Signature is retrieved
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindCapHdrFFS(
+ IN VOID *pCapsule,
+ OUT UINT8 **pFfsData
+)
+{
+ UINT32 Signature;
+ UINT32 *SearchPointer;
+ AMI_FFS_COMMON_SECTION_HEADER *FileSection;
+ APTIO_FW_CAPSULE_HEADER *pFwCapHdr;
+
+ SearchPointer = (UINT32 *)((UINT8 *)pCapsule - sizeof(AMI_FFS_COMMON_SECTION_HEADER) + FLASH_SIZE);
+ Signature = gFwCapFfsGuid.Data1;
+ do {
+ if(*SearchPointer == Signature) {
+ FileSection = (AMI_FFS_COMMON_SECTION_HEADER *)SearchPointer;
+ if(!guidcmp(&gFwCapFfsGuid, &(FileSection->FfsHdr.Name))
+ && !guidcmp(&FwCapSectionGuid, &(FileSection->SectionGuid))
+ ){
+ pFwCapHdr = (APTIO_FW_CAPSULE_HEADER*)(FileSection->FwCapHdr);
+ // just a sanity check - Cap Size must match the Section size
+ if(((*(UINT32 *)FileSection->FfsHdr.Size) & 0xffffff) >=
+ pFwCapHdr->CapHdr.HeaderSize + sizeof(AMI_FFS_COMMON_SECTION_HEADER) &&
+ !guidcmp((EFI_GUID*)&pFwCapHdr->CapHdr.CapsuleGuid, &gFWCapsuleGuid)
+ ){
+ *pFfsData = (UINT8*)pFwCapHdr;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ } while(SearchPointer-- != pCapsule);
+
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: HashFwRomMapImage
+//
+// Description: The Rom image hash is calculated based on info from the Rom Area map
+//
+// Input:
+// Payload - pointer to a FW Image
+// FwCapsuleHdr - pointer to a FW Capsule Hdr
+// RomSize - Size of Rom Image
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_DEVICE_ERROR - capsule processing failed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS HashFwRomMapImage (
+ IN APTIO_FW_CAPSULE_HEADER *FWCapsuleHdr,
+ IN UINT8 *Payload,
+ IN UINTN RomSize,
+ OUT UINT8 *gHashDB
+){
+ EFI_STATUS Status = EFI_SUCCESS;
+ ROM_AREA *RomAreaTbl;
+ UINTN *Addr;
+ UINTN *Len;
+ UINTN i, RomMap_size, max_num_elem, num_elem, max_hash_elem;
+
+ RomAreaTbl = (ROM_AREA *)(UINTN)((UINT32)FWCapsuleHdr+FWCapsuleHdr->RomLayoutOffset);
+
+ RomMap_size = FWCapsuleHdr->RomImageOffset-FWCapsuleHdr->RomLayoutOffset;
+ max_num_elem = RomMap_size/sizeof(ROM_AREA);
+// assume max size of RomMap array = RomMap_size/sizeof(ROM_AREA);
+// or better yet ...calculate exact number
+ num_elem = 0;
+ for (i=0; i < max_num_elem && RomAreaTbl[i].Size != 0; i++ )
+ {
+ if (RomAreaTbl[i].Attributes & ROM_AREA_FV_SIGNED)
+ num_elem++;
+ }
+ max_num_elem = i;
+ max_hash_elem = num_elem+2; // add 2 extra entries
+ Addr = (UINTN*)gHashTbl;
+ Len = (UINTN*)((UINT8*)gHashTbl + max_hash_elem*sizeof(UINTN));
+
+ num_elem = 0;
+ for (i=0; i < max_num_elem && num_elem < max_hash_elem && RomAreaTbl[i].Size != 0; i++)
+ {
+ if (!(RomAreaTbl[i].Attributes & ROM_AREA_FV_SIGNED))
+ continue;
+ // sanity check for buffer overruns
+ if(RomAreaTbl[i].Offset > RomSize ||
+ (UINT64)RomAreaTbl[i].Offset + RomAreaTbl[i].Size > RomSize)
+ return EFI_SECURITY_VIOLATION;
+ // RomArea only holds offsets within a payload
+ Addr[num_elem] = (UINTN)((UINTN)Payload + RomAreaTbl[i].Offset);
+ Len[num_elem] = RomAreaTbl[i].Size;
+//TRACE((-1, "\n Num %d: Offs = %X (%X), len %X\n", num_elem, /*Addr[num_elem]*/RomAreaTbl[i].Offset, (UINT32)*(UINT32*)Addr[num_elem], Len[num_elem]));
+
+ num_elem++;
+
+ }
+ if(num_elem >= max_hash_elem) return EFI_SECURITY_VIOLATION;
+//
+// Hash of Capsule Hdr + FW Certificate Hdr
+//
+ if(FWCapsuleHdr->CapHdr.Flags & CAPSULE_FLAGS_CAPHDR_IN_SIGNCERT) {
+ Addr[num_elem] = (UINTN) FWCapsuleHdr;
+ Len[num_elem] = (UINTN)&FWCapsuleHdr->FWCert.SignCert.CertData - (UINTN)FWCapsuleHdr;
+//TRACE((-1, "\n Num %d: Offs = %X (%X), len %X\n", num_elem, Addr[num_elem], (UINT32)*(UINT32*)Addr[num_elem], Len[num_elem]));
+ num_elem++;
+ if(num_elem >= max_hash_elem) return EFI_SECURITY_VIOLATION;
+ }
+//
+// Hash of the ROM_MAP table
+//
+ Addr[num_elem] = (UINTN)RomAreaTbl;
+ Len[num_elem] = (i+1)*sizeof(ROM_AREA);
+//TRACE((-1, "\n Num %d: Offs = %X (%X), len %X\n", num_elem, Addr[num_elem], (UINT32)*(UINT32*)Addr[num_elem], Len[num_elem]));
+ num_elem++;
+
+ Status = gAmiSig->Hash(gAmiSig, &gEfiHashAlgorithmSha256Guid,
+ num_elem, (const UINT8**)Addr, (const UINTN*)Len, gHashDB );
+
+//TRACE((-1, "\nHash the FW Image %r\nNumElems = %d\n", Status, num_elem));
+
+//for (i=0; i<16; i++)
+// TRACE((-1,"%02X ", (gHashDB[i]) ));
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VerifyFwCertPkcs7
+//
+// Description: This code verifies FW Capsule is genuine,
+// and performs following checks on the image:
+// 1. Signing certificate is signed with trusted Root Platform key
+// 2. Integrity check. Image Signature verification
+//
+// Input:
+// Payload - pointer to a FW Image
+// FwCapsuleHdr - pointer to a FW Capsule Hdr
+// RomSize - Size of Rom Image
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_DEVICE_ERROR - capsule processing failed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS VerifyFwCertPkcs7 (
+ IN APTIO_FW_CAPSULE_HEADER *FWCapsuleHdr,
+ IN UINT8 *Payload,
+ IN UINTN RomSize
+){
+ EFI_STATUS Status;
+ UINT8 *Pkcs7Cert, *pDigest;
+ UINTN Pkcs7Cert_len, DigestLen;
+ UINT32 Flags=0;
+
+// TRACE((-1, "Verify Fw Pkcs7 Cert\n"));
+//
+// 1. Verify Platform Key algo matches x509 cert
+//
+ if(guidcmp(&gpPubKeyHndl.AlgGuid, &gEfiCertX509Guid))
+ return EFI_UNSUPPORTED;
+
+// 2. Verify Signing Cert Signature
+//
+// 2.1 The Rom image hash is calculated based on info from the Rom Area map
+//
+ Status = HashFwRomMapImage(FWCapsuleHdr, Payload, RomSize, gHashDB);
+ if (EFI_ERROR(Status)) return Status;
+
+// 2.2 Verify Fw Certificate
+ pDigest = &gHashDB[0];
+ DigestLen = SHA256_DIGEST_SIZE;
+ Pkcs7Cert = (UINT8*)&FWCapsuleHdr->FWCert.SignCert.CertData;
+ Pkcs7Cert_len = FWCapsuleHdr->FWCert.SignCert.Hdr.Hdr.dwLength-sizeof(WIN_CERTIFICATE_UEFI_GUID_1);
+ Status = gAmiSig->Pkcs7Verify( gAmiSig,
+ Pkcs7Cert, Pkcs7Cert_len, // Pkcs7Cert
+ gpPubKeyHndl.Blob, gpPubKeyHndl.BlobSize, // TrustCert
+ &pDigest, &DigestLen, // In/OutData
+ Pkcs7CertValidate,
+ RELEASE // Flags, mutex
+ );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VerifyFwCertRsa2048Sha256
+//
+// Description: This code verifies FW Capsule is genuine,
+// and performs following checks on the image:
+// 1. Signing certificate is signed with trusted Root Platform key
+// 2. Integrity check. Image Signature verification
+//
+// Input:
+// Payload - pointer to a FW Image
+// FwCapsuleHdr - pointer to a FW Capsule Hdr
+// RomSize - Size of Rom Image
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_DEVICE_ERROR - capsule processing failed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS VerifyFwCertRsa2048Sha256 (
+ IN APTIO_FW_CAPSULE_HEADER *FWCapsuleHdr,
+ IN UINT8 *Payload,
+ IN UINTN RomSize
+){
+ EFI_STATUS Status;
+ CRYPT_HANDLE HashHndl;
+ CRYPT_HANDLE PubKeyHndl;
+ UINT8 *pSig;
+ UINT32 Flags;
+ UINT8 *Addr;
+ UINTN Size;
+ EFI_CERT_BLOCK_RSA_2048_SHA256* pRootCert;
+
+// Version 010 and later supporting extended flags
+// if(FWCapsuleHdr->CapHdr.Flags & CAPSULE_FLAGS_CAPHDR_IN_SIGNCERT)
+ if(FWCapsuleHdr->CapHdr.HeaderSize == FWCapsuleHdr->RomImageOffset)
+ {
+ if(FWCapsuleHdr->CapHdr.Flags & CAPSULE_FLAGS_RSA_PSS_PADDING_SCHEME)
+ Flags = EFI_CRYPT_RSASSA_PSS;
+ else
+ Flags = EFI_CRYPT_RSASSA_PKCS1V15;
+ }
+ else
+ Flags = EFI_CRYPT_RSASSA_PSS;
+
+ HashHndl.AlgGuid = gEfiHashAlgorithmSha256Guid;
+ HashHndl.BlobSize = SHA256_DIGEST_SIZE;
+ HashHndl.Blob = gHashDB;
+
+ PubKeyHndl.AlgGuid = gEfiCertRsa2048Guid;
+ PubKeyHndl.BlobSize = DEFAULT_RSA_KEY_MODULUS_LEN;
+//
+// 1. Compare Capsule's Sign Cert key with Platform Root Key
+//
+ PubKeyHndl.Blob = (UINT8*)FWCapsuleHdr->FWCert.SignCert.CertData.PublicKey;
+ Status = gAmiSig->VerifyKey(gAmiSig, &gPRKeyGuid, &PubKeyHndl);
+ // Skip the RootCert key checking if SignCert Key and PR Key are matching
+//TRACE((-1, "Compare SignCert Key == FW Key(%X) : %r\n", (UINT32)*PubKeyHndl.Blob, Status));
+ if(EFI_ERROR(Status)) {
+//
+// 1.1 Compare Platform Root with Capsule's Key from a Root Key store
+//
+ for (pRootCert = &FWCapsuleHdr->FWCert.RootCert;
+ (UINT8*)pRootCert <
+ (UINT8*)&FWCapsuleHdr->FWCert+FWCapsuleHdr->FWCert.SignCert.Hdr.Hdr.dwLength &&
+ pRootCert->PublicKey[0]!=0;
+ pRootCert++)
+ {
+ PubKeyHndl.Blob = pRootCert->PublicKey;
+ Status = gAmiSig->VerifyKey(gAmiSig, &gPRKeyGuid, &PubKeyHndl);
+//TRACE((-1, "Compare RootCert Key == FW Key(%X) : %r\n", (UINT32)*PubKeyHndl.Blob, Status));
+ if (EFI_ERROR(Status)) continue;
+//
+// 2. Verify RootCert.Signature
+//
+// 2.1 Compute FWCert.SignCert.PublicKey Hash
+ if(FWCapsuleHdr->CapHdr.Flags & CAPSULE_FLAGS_SIGNKEY_IN_ROOTCERT)
+ {
+ Addr = (UINT8*)&FWCapsuleHdr->FWCert.SignCert.CertData.PublicKey;
+ Size = DEFAULT_RSA_KEY_MODULUS_LEN;
+ } else
+// 2.2 Compute FWCert.SignCert Hash
+ {
+ Addr = (UINT8*)&FWCapsuleHdr->FWCert.SignCert;
+ Size = sizeof(AMI_CERTIFICATE_RSA2048_SHA256);
+ }
+
+ Status = gAmiSig->Hash(gAmiSig, &gEfiHashAlgorithmSha256Guid, 1,&Addr,(const UINTN*)&Size, gHashDB);
+ if (EFI_ERROR(Status)) break;
+
+ pSig = (void*)pRootCert->Signature;
+ Status = gAmiSig->Pkcs1Verify(gAmiSig, &PubKeyHndl, &HashHndl, pSig, DEFAULT_RSA_SIG_LEN, Flags);
+//TRACE((-1, "Verify Root Cert : %r\n", Status));
+ break;
+ }
+ }
+ if (EFI_ERROR(Status)) return EFI_SECURITY_VIOLATION;
+// 3. Verify Signing Cert Signature
+//
+// 3.1 The Rom image hash is calculated based on info from the Rom Area map
+//
+ Status = HashFwRomMapImage(FWCapsuleHdr, Payload, RomSize, gHashDB);
+ if (EFI_ERROR(Status)) return Status;
+
+ pSig = (void*)FWCapsuleHdr->FWCert.SignCert.CertData.Signature;
+ PubKeyHndl.Blob = (UINT8*)FWCapsuleHdr->FWCert.SignCert.CertData.PublicKey;
+ Status = gAmiSig->Pkcs1Verify(gAmiSig, &PubKeyHndl, &HashHndl, pSig, DEFAULT_RSA_SIG_LEN, Flags);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CapsuleValidate
+//
+// Description: This code verifies FW Capsule is genuine,
+// and performs following checks on the image:
+// 1. Re-Play protection. Verifies that new FW image version is newer then the current one
+// 2. Signing certificate is signed with trusted Root Platform key
+// 3. Integrity check. Image Signature verification
+//
+// Input:
+// IN VOID *pFwCapsule - pointer to a FW Image
+// OUT UINT8 *pFwCapsuleHdr - return a pointer to a FW Capsule Hdr(optional if parameter is not NULL)
+//
+// Output: EFI_SUCCESS - capsule processed successfully
+// EFI_SECURITY_VIOLATION - capsule processing failed
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CapsuleValidate (
+ IN OUT UINT8 **pFwCapsule,
+ IN OUT APTIO_FW_CAPSULE_HEADER **pFWCapsuleHdr
+){
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ APTIO_FW_CAPSULE_HEADER *FWCapsuleHdr;
+ UINTN RomSize;
+ UINT8 *Payload;
+
+ FWCapsuleHdr = (APTIO_FW_CAPSULE_HEADER*)*pFwCapsule;
+ Payload = (UINT8*)*pFwCapsule;
+ RomSize = FLASH_SIZE;
+
+/*
+ - CapsuleValidate
+ - Look up Capsule GUID
+ - Found -
+ update pFwCapsule ptr to beginning of BIOS ROM data
+ continue with Image Verify
+ - Not found at offs 0 - assume Cap Hdr in FFS
+ Call GetSigFFS
+ locate FFS by Hole GUID, Sec GUID
+ if found, update FWCapsuleHdr,
+ continue with Image Verify
+*/
+// proper FW Capsule presence check
+
+// verify Capsule Mailbox points to FW_CAPSULE hdr
+ if(!guidcmp((EFI_GUID*)&FWCapsuleHdr->CapHdr.CapsuleGuid, &gFWCapsuleGuid))
+ {
+// Update pFwCapsule to point to beginning of Bios ROM
+ Payload = (UINT8*)((UINT32)FWCapsuleHdr + FWCapsuleHdr->RomImageOffset);
+ RomSize = (FWCapsuleHdr->CapHdr.CapsuleImageSize - FWCapsuleHdr->RomImageOffset);
+ *pFwCapsule = Payload;
+ }
+ else
+ {
+//TRACE((-1, "Looking for embedded Signature...\n"));
+ if(EFI_ERROR(FindCapHdrFFS(Payload, (UINT8**)&FWCapsuleHdr)))
+ return EFI_SECURITY_VIOLATION;
+ }
+TRACE((-1, "Found Fw Capsule GUID %g\n\r", &(FWCapsuleHdr->CapHdr.CapsuleGuid)));
+
+// update return argument with a ptr to FwCapHdr
+ if(pFWCapsuleHdr)
+ *pFWCapsuleHdr = FWCapsuleHdr;
+
+// Aptio FW Capsule only supporting WIN_CERT_TYPE_EFI_GUID
+ if(FWCapsuleHdr->FWCert.SignCert.Hdr.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID)
+ return EFI_SECURITY_VIOLATION;
+
+// sanity check for buffer overruns
+ if((FWCapsuleHdr->CapHdr.CapsuleImageSize > gFwCapMaxSize) ||
+ (FWCapsuleHdr->RomImageOffset > (FWCAPSULE_IMAGE_SIZE-FLASH_SIZE)) || // 16k is a MAX possible FwCap Hdr size
+ (FWCapsuleHdr->CapHdr.HeaderSize > FWCapsuleHdr->RomImageOffset) ||
+ (FWCapsuleHdr->RomLayoutOffset > FWCapsuleHdr->RomImageOffset) ||
+ (FWCapsuleHdr->FWCert.SignCert.Hdr.Hdr.dwLength + offsetof(APTIO_FW_CAPSULE_HEADER, FWCert) >
+ FWCapsuleHdr->RomLayoutOffset )
+ )
+ return EFI_SECURITY_VIOLATION;
+
+ if(!IsAddressInSmram((EFI_PHYSICAL_ADDRESS)gpPubKeyHndl.Blob, gpPubKeyHndl.BlobSize) )
+ return EFI_SECURITY_VIOLATION;
+ TRACE((TRACE_ALWAYS,"gpKey (%x, %x bytes)\n",gpPubKeyHndl.Blob,gpPubKeyHndl.BlobSize));
+// Begin Authentication
+ if(!guidcmp((EFI_GUID*)&FWCapsuleHdr->FWCert.SignCert.Hdr.CertType, &gEfiCertTypePkcs7Guid))
+ Status = VerifyFwCertPkcs7(FWCapsuleHdr, Payload, RomSize);
+ else
+ Status = VerifyFwCertRsa2048Sha256(FWCapsuleHdr, Payload, RomSize);
+ TRACE((-1, "Signature validate %r\n", Status));
+ if (EFI_ERROR(Status)) return Status;
+//
+// Local PEI $FID is linked with CspLib. extern FW_VERSION FwVersionData;
+// Find $FID in new Fw FVs. Any found should do for us. Use RomMap from Capsule's Hdr
+// compare local BB and Main $Fid BIOS Major/Minor revs with New one.
+#if IGNORE_RUNTIME_UPDATE_IMAGE_REVISION_CHECK == 0
+ Status = VerifyFwRevision(FWCapsuleHdr, Payload);
+//TRACE((-1, "FW Revision test %r\n", Status));
+#endif
+
+//TRACE((-1, "Capsule Verify %r\n", Status));
+
+ return Status;
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2014, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************