]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
Enable TPM measurement lib to measure all PE image from a FV unmeasured by TcgPei
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / DxeImageVerificationLib.c
index 91977522a9138cd9c751f543d22c0def0a553ce1..9ea3a28ad91b93ede65c6eb159ad5b6b75c52b08 100644 (file)
@@ -1,7 +1,18 @@
 /** @file\r
   Implement image verification services for secure boot service in UEFI2.3.1.\r
 \r
-Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Caution: This file requires additional review when modified.\r
+  This library will have external input - PE/COFF image.\r
+  This external input must be validated carefully to avoid security issue like\r
+  buffer overflow, integer overflow.\r
+\r
+  DxeImageVerificationLibImageRead() function will make sure the PE/COFF image content\r
+  read is within the image buffer.\r
+\r
+  DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept\r
+  untrusted PE/COFF image and validate its data structure within this image buffer before use.\r
+\r
+Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -14,14 +25,21 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "DxeImageVerificationLib.h"\r
 \r
+//\r
+// Caution: This is used by a function which may receive untrusted input.\r
+// These global variables hold PE/COFF image data, and they should be validated before use.\r
+//\r
 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;\r
-UINTN                               mImageSize;\r
 UINT32                              mPeCoffHeaderOffset;\r
+EFI_GUID                            mCertType;\r
+\r
+//\r
+// Information on current PE/COFF image\r
+//\r
+UINTN                               mImageSize;\r
+UINT8                               *mImageBase       = NULL;\r
 UINT8                               mImageDigest[MAX_DIGEST_SIZE];\r
 UINTN                               mImageDigestSize;\r
-EFI_IMAGE_DATA_DIRECTORY            *mSecDataDir      = NULL;\r
-UINT8                               *mImageBase       = NULL;\r
-EFI_GUID                            mCertType;\r
 \r
 //\r
 // Notify string for authorization UI.\r
@@ -54,6 +72,54 @@ HASH_TABLE mHash[] = {
   { L"SHA512", 64, &mHashOidValue[40], 9, NULL,                NULL,       NULL,          NULL       }\r
 };\r
 \r
+/**\r
+  Reads contents of a PE/COFF image in memory buffer.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will make sure the PE/COFF image content\r
+  read is within the image buffer.\r
+\r
+  @param  FileHandle      Pointer to the file handle to read the PE/COFF image.\r
+  @param  FileOffset      Offset into the PE/COFF image to begin the read operation.\r
+  @param  ReadSize        On input, the size in bytes of the requested read operation.  \r
+                          On output, the number of bytes actually read.\r
+  @param  Buffer          Output buffer that contains the data read from the PE/COFF image.\r
+  \r
+  @retval EFI_SUCCESS     The specified portion of the PE/COFF image was read and the size \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeImageVerificationLibImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINTN   *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+{\r
+  UINTN               EndPosition;\r
+\r
+  if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
+    return EFI_INVALID_PARAMETER;    \r
+  }\r
+\r
+  if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  EndPosition = FileOffset + *ReadSize;\r
+  if (EndPosition > mImageSize) {\r
+    *ReadSize = (UINT32)(mImageSize - FileOffset);\r
+  }\r
+\r
+  if (FileOffset >= mImageSize) {\r
+    *ReadSize = 0;\r
+  }\r
+\r
+  CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 \r
 /**\r
   Get the image type.\r
@@ -74,6 +140,10 @@ GetImageType (
   EFI_DEVICE_PATH_PROTOCOL          *TempDevicePath;\r
   EFI_BLOCK_IO_PROTOCOL             *BlockIo;\r
 \r
+  if (File == NULL) {\r
+    return IMAGE_UNKNOWN;\r
+  }\r
+\r
   //\r
   // First check to see if File is from a Firmware Volume\r
   //\r
@@ -185,6 +255,10 @@ GetImageType (
   Caculate hash of Pe/Coff image based on the authenticode image hashing in\r
   PE/COFF Specification 8.0 Appendix A\r
 \r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will validate its data structure\r
+  within this image buffer before use.\r
+\r
   @param[in]    HashAlg   Hash algorithm type.\r
 \r
   @retval TRUE            Successfully hash image.\r
@@ -207,8 +281,8 @@ HashPeImage (
   EFI_IMAGE_SECTION_HEADER  *SectionHeader;\r
   UINTN                     Index;\r
   UINTN                     Pos;\r
-  UINTN                     SumOfSectionBytes;\r
-  EFI_IMAGE_SECTION_HEADER  *SectionCache;\r
+  UINT32                    CertSize;\r
+  UINT32                    NumberOfRvaAndSizes;\r
 \r
   HashCtx       = NULL;\r
   SectionHeader = NULL;\r
@@ -248,11 +322,26 @@ HashPeImage (
   if (!Status) {\r
     goto Done;\r
   }\r
+\r
   //\r
   // Measuring PE/COFF Image Header;\r
   // But CheckSum field and SECURITY data directory (certificate) are excluded\r
   //\r
-  Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
+  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value \r
+    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the \r
+    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
+    //\r
+    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+  } else {\r
+    //\r
+    // Get the magic value from the PE/COFF Optional Header\r
+    //\r
+    Magic =  mNtHeader.Pe32->OptionalHeader.Magic;\r
+  }\r
+  \r
   //\r
   // 3.  Calculate the distance from the base of the image header to the image checksum address.\r
   // 4.  Hash the image header from its base to beginning of the image checksum.\r
@@ -263,11 +352,13 @@ HashPeImage (
     // Use PE32 offset.\r
     //\r
     HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
+    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
   } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
     //\r
     // Use PE32+ offset.\r
     //\r
     HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
+    NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
   } else {\r
     //\r
     // Invalid header magic number.\r
@@ -280,51 +371,86 @@ HashPeImage (
   if (!Status) {\r
     goto Done;\r
   }\r
+\r
   //\r
   // 5.  Skip over the image checksum (it occupies a single ULONG).\r
-  // 6.  Get the address of the beginning of the Cert Directory.\r
-  // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.\r
   //\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+  if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
     //\r
-    // Use PE32 offset.\r
+    // 6.  Since there is no Cert Directory in optional header, hash everything\r
+    //     from the end of the checksum to the end of image header.\r
     //\r
-    HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
-    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset.\r
+      //\r
+      HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+    } else {\r
+      //\r
+      // Use PE32+ offset.\r
+      //\r
+      HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+    }\r
+\r
+    if (HashSize != 0) {\r
+      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+      if (!Status) {\r
+        goto Done;\r
+      }\r
+    }\r
   } else {\r
     //\r
-    // Use PE32+ offset.\r
+    // 7.  Hash everything from the end of the checksum to the start of the Cert Directory.\r
     //\r
-    HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
-    HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
-  }\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset.\r
+      //\r
+      HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+    } else {\r
+      //\r
+      // Use PE32+ offset.\r
+      //\r
+      HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
+      HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+    }\r
+\r
+    if (HashSize != 0) {\r
+      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+      if (!Status) {\r
+        goto Done;\r
+      }\r
+    }\r
 \r
-  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  //\r
-  // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
-  // 9.  Hash everything from the end of the Cert Directory to the end of image header.\r
-  //\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-    //\r
-    // Use PE32 offset\r
-    //\r
-    HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-    HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
-  } else {\r
     //\r
-    // Use PE32+ offset.\r
+    // 8.  Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
+    // 9.  Hash everything from the end of the Cert Directory to the end of image header.\r
     //\r
-    HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
-    HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase);\r
-  }\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset\r
+      //\r
+      HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+      HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+    } else {\r
+      //\r
+      // Use PE32+ offset.\r
+      //\r
+      HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
+      HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+    }\r
 \r
-  Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
-  if (!Status) {\r
-    goto Done;\r
+    if (HashSize != 0) {\r
+      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+      if (!Status) {\r
+        goto Done;\r
+      }\r
+    }    \r
   }\r
+\r
   //\r
   // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
   //\r
@@ -349,20 +475,6 @@ HashPeImage (
                mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
                );\r
 \r
-  SectionCache = Section;\r
-  for (Index = 0, SumOfSectionBytes = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++, SectionCache++) {\r
-    SumOfSectionBytes += SectionCache->SizeOfRawData;\r
-  }\r
-\r
-  //\r
-  // Sanity check for file corruption. Sections raw data size should be smaller\r
-  // than Image Size.\r
-  //\r
-  if (SumOfSectionBytes >= mImageSize) {\r
-    Status = FALSE;\r
-    goto Done;\r
-  }\r
-\r
   //\r
   // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER\r
   //     structures in the image. The 'NumberOfSections' field of the image\r
@@ -421,29 +533,36 @@ HashPeImage (
   //\r
   if (mImageSize > SumOfBytesHashed) {\r
     HashBase = mImageBase + SumOfBytesHashed;\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-      //\r
-      // Use PE32 offset.\r
-      //\r
-      HashSize = (UINTN)(\r
-                 mImageSize -\r
-                 mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
-                 SumOfBytesHashed);\r
+\r
+    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      CertSize = 0;\r
     } else {\r
-      //\r
-      // Use PE32+ offset.\r
-      //\r
-      HashSize = (UINTN)(\r
-                 mImageSize -\r
-                 mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size -\r
-                 SumOfBytesHashed);\r
+      if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+        //\r
+        // Use PE32 offset.\r
+        //\r
+        CertSize = mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
+      } else {\r
+        //\r
+        // Use PE32+ offset.\r
+        //\r
+        CertSize = mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;\r
+      }\r
     }\r
 \r
-    Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
-    if (!Status) {\r
+    if (mImageSize > CertSize + SumOfBytesHashed) {\r
+      HashSize = (UINTN) (mImageSize - CertSize - SumOfBytesHashed);\r
+\r
+      Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
+      if (!Status) {\r
+        goto Done;\r
+      }\r
+    } else if (mImageSize < CertSize + SumOfBytesHashed) {\r
+      Status = FALSE;\r
       goto Done;\r
     }\r
   }\r
+\r
   Status  = mHash[HashAlg].HashFinal(HashCtx, mImageDigest);\r
 \r
 Done:\r
@@ -461,19 +580,24 @@ Done:
   Pe/Coff image based on the authenticode image hashing in PE/COFF Specification\r
   8.0 Appendix A\r
 \r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will validate its data structure\r
+  within this image buffer before use.\r
+\r
+  @param[in]  AuthData            Pointer to the Authenticode Signature retrieved from signed image.\r
+  @param[in]  AuthDataSize        Size of the Authenticode Signature in bytes.\r
+  \r
   @retval EFI_UNSUPPORTED             Hash algorithm is not supported.\r
   @retval EFI_SUCCESS                 Hash successfully.\r
 \r
 **/\r
 EFI_STATUS\r
 HashPeImageByType (\r
-  VOID\r
+  IN UINT8              *AuthData,\r
+  IN UINTN              AuthDataSize\r
   )\r
 {\r
   UINT8                     Index;\r
-  WIN_CERTIFICATE_EFI_PKCS  *PkcsCertData;\r
-\r
-  PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);\r
 \r
   for (Index = 0; Index < HASHALG_MAX; Index++) {\r
     //\r
@@ -486,8 +610,20 @@ HashPeImageByType (
     //            .... }\r
     //    The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing\r
     //    This field has the fixed offset (+32) in final Authenticode ASN.1 data.\r
+    //    Fixed offset (+32) is calculated based on two bytes of length encoding.\r
     //\r
-    if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
+    if ((*(AuthData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {\r
+      //\r
+      // Only support two bytes of Long Form of Length Encoding.\r
+      //\r
+      continue;\r
+    }\r
+\r
+    if (AuthDataSize < 32 + mHash[Index].OidLength) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    if (CompareMem (AuthData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
       break;\r
     }\r
   }\r
@@ -646,60 +782,6 @@ AddImageExeInfo (
   }\r
 }\r
 \r
-/**\r
-  Discover if the UEFI image is authorized by user's policy setting.\r
-\r
-  @param[in]    Policy            Specify platform's policy setting.\r
-\r
-  @retval EFI_ACCESS_DENIED       Image is not allowed to run.\r
-  @retval EFI_SECURITY_VIOLATION  Image is deferred.\r
-  @retval EFI_SUCCESS             Image is authorized to run.\r
-\r
-**/\r
-EFI_STATUS\r
-ImageAuthorization (\r
-  IN UINT32     Policy\r
-  )\r
-{\r
-  EFI_STATUS    Status;\r
-  EFI_INPUT_KEY Key;\r
-\r
-  Status = EFI_ACCESS_DENIED;\r
-\r
-  switch (Policy) {\r
-\r
-  case QUERY_USER_ON_SECURITY_VIOLATION:\r
-    do {\r
-      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, mNotifyString1, mNotifyString2, NULL);\r
-      if (Key.UnicodeChar == L'Y' || Key.UnicodeChar == L'y') {\r
-        Status = EFI_SUCCESS;\r
-        break;\r
-      } else if (Key.UnicodeChar == L'N' || Key.UnicodeChar == L'n') {\r
-        Status = EFI_ACCESS_DENIED;\r
-        break;\r
-      } else if (Key.UnicodeChar == L'D' || Key.UnicodeChar == L'd') {\r
-        Status = EFI_SECURITY_VIOLATION;\r
-        break;\r
-      }\r
-    } while (TRUE);\r
-    break;\r
-\r
-  case ALLOW_EXECUTE_ON_SECURITY_VIOLATION:\r
-    Status = EFI_SUCCESS;\r
-    break;\r
-\r
-  case DEFER_EXECUTE_ON_SECURITY_VIOLATION:\r
-    Status = EFI_SECURITY_VIOLATION;\r
-    break;\r
-\r
-  case DENY_EXECUTE_ON_SECURITY_VIOLATION:\r
-    Status = EFI_ACCESS_DENIED;\r
-    break;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
 /**\r
   Check whether signature is in specified database.\r
 \r
@@ -789,8 +871,10 @@ Done:
   Verify PKCS#7 SignedData using certificate found in Variable which formatted\r
   as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.\r
 \r
-  @param VariableName  Name of Variable to search for Certificate.\r
-  @param VendorGuid    Variable vendor GUID.\r
+  @param[in]  AuthData      Pointer to the Authenticode Signature retrieved from signed image.\r
+  @param[in]  AuthDataSize  Size of the Authenticode Signature in bytes.\r
+  @param[in]  VariableName  Name of Variable to search for Certificate.\r
+  @param[in]  VendorGuid    Variable vendor GUID.\r
 \r
   @retval TRUE         Image pass verification.\r
   @retval FALSE        Image fail verification.\r
@@ -798,13 +882,14 @@ Done:
 **/\r
 BOOLEAN\r
 IsPkcsSignedDataVerifiedBySignatureList (\r
+  IN UINT8              *AuthData,\r
+  IN UINTN              AuthDataSize,\r
   IN CHAR16             *VariableName,\r
   IN EFI_GUID           *VendorGuid\r
   )\r
 {\r
   EFI_STATUS                Status;\r
   BOOLEAN                   VerifyStatus;\r
-  WIN_CERTIFICATE_EFI_PKCS  *PkcsCertData;\r
   EFI_SIGNATURE_LIST        *CertList;\r
   EFI_SIGNATURE_DATA        *Cert;\r
   UINTN                     DataSize;\r
@@ -820,7 +905,6 @@ IsPkcsSignedDataVerifiedBySignatureList (
   RootCert     = NULL;\r
   RootCertSize = 0;\r
   VerifyStatus = FALSE;\r
-  PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);\r
 \r
   DataSize = 0;\r
   Status   = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
@@ -848,14 +932,14 @@ IsPkcsSignedDataVerifiedBySignatureList (
           // Iterate each Signature Data Node within this CertList for verify.\r
           //\r
           RootCert      = Cert->SignatureData;\r
-          RootCertSize  = CertList->SignatureSize;\r
+          RootCertSize  = CertList->SignatureSize - sizeof (EFI_GUID);\r
 \r
           //\r
           // Call AuthenticodeVerify library to Verify Authenticode struct.\r
           //\r
           VerifyStatus = AuthenticodeVerify (\r
-                           PkcsCertData->CertData,\r
-                           mSecDataDir->Size - sizeof(PkcsCertData->Hdr),\r
+                           AuthData,\r
+                           AuthDataSize,\r
                            RootCert,\r
                            RootCertSize,\r
                            mImageDigest,\r
@@ -883,19 +967,23 @@ Done:
 /**\r
   Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.\r
 \r
+  @param[in]  AuthData      Pointer to the Authenticode Signature retrieved from signed image.\r
+  @param[in]  AuthDataSize  Size of the Authenticode Signature in bytes.\r
+\r
   @retval EFI_SUCCESS                 Image pass verification.\r
   @retval EFI_SECURITY_VIOLATION      Image fail verification.\r
 \r
 **/\r
 EFI_STATUS\r
 VerifyCertPkcsSignedData (\r
-  VOID\r
+  IN UINT8              *AuthData,\r
+  IN UINTN              AuthDataSize\r
   )\r
 {\r
   //\r
   // 1: Find certificate from DBX forbidden database for revoked certificate.\r
   //\r
-  if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {\r
+  if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {\r
     //\r
     // DBX is forbidden database, if Authenticode verification pass with\r
     // one of the certificate in DBX, this image should be rejected.\r
@@ -904,149 +992,9 @@ VerifyCertPkcsSignedData (
   }\r
 \r
   //\r
-  // 2: Find certificate from KEK database and try to verify authenticode struct.\r
-  //\r
-  if (IsPkcsSignedDataVerifiedBySignatureList (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid)) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // 3: Find certificate from DB database and try to verify authenticode struct.\r
-  //\r
-  if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {\r
-    return EFI_SUCCESS;\r
-  } else {\r
-    return EFI_SECURITY_VIOLATION;\r
-  }\r
-}\r
-\r
-/**\r
-  Verify certificate in WIN_CERTIFICATE_UEFI_GUID format.\r
-\r
-  @retval EFI_SUCCESS                 Image pass verification.\r
-  @retval EFI_SECURITY_VIOLATION      Image fail verification.\r
-  @retval other error value\r
-\r
-**/\r
-EFI_STATUS\r
-VerifyCertUefiGuid (\r
-  VOID\r
-  )\r
-{\r
-  BOOLEAN                         Status;\r
-  WIN_CERTIFICATE_UEFI_GUID       *EfiCert;\r
-  EFI_SIGNATURE_LIST              *KekList;\r
-  EFI_SIGNATURE_DATA              *KekItem;\r
-  EFI_CERT_BLOCK_RSA_2048_SHA256  *CertBlock;\r
-  VOID                            *Rsa;\r
-  UINTN                           KekCount;\r
-  UINTN                           Index;\r
-  UINTN                           KekDataSize;\r
-  BOOLEAN                         IsFound;\r
-  EFI_STATUS                      Result;\r
-\r
-  EfiCert   = NULL;\r
-  KekList   = NULL;\r
-  KekItem   = NULL;\r
-  CertBlock = NULL;\r
-  Rsa       = NULL;\r
-  Status    = FALSE;\r
-  IsFound   = FALSE;\r
-  KekDataSize = 0;\r
-\r
-  EfiCert   = (WIN_CERTIFICATE_UEFI_GUID *) (mImageBase + mSecDataDir->VirtualAddress);\r
-  CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) EfiCert->CertData;\r
-  if (!CompareGuid (&EfiCert->CertType, &gEfiCertTypeRsa2048Sha256Guid)) {\r
-    //\r
-    // Invalid Certificate Data Type.\r
-    //\r
-    return EFI_SECURITY_VIOLATION;\r
-  }\r
-\r
-  //\r
-  // Get KEK database variable data size\r
+  // 2: Find certificate from DB database and try to verify authenticode struct.\r
   //\r
-  Result = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &KekDataSize, NULL);\r
-  if (Result != EFI_BUFFER_TOO_SMALL) {\r
-    return EFI_SECURITY_VIOLATION;\r
-  }\r
-\r
-  //\r
-  // Get KEK database variable.\r
-  //\r
-  KekList = GetEfiGlobalVariable (EFI_KEY_EXCHANGE_KEY_NAME);\r
-  if (KekList == NULL) {\r
-    return EFI_SECURITY_VIOLATION;\r
-  }\r
-\r
-  //\r
-  // Enumerate all Kek items in this list to verify the variable certificate data.\r
-  // If anyone is authenticated successfully, it means the variable is correct!\r
-  //\r
-  while ((KekDataSize > 0) && (KekDataSize >= KekList->SignatureListSize)) {\r
-    if (CompareGuid (&KekList->SignatureType, &gEfiCertRsa2048Guid)) {\r
-      KekItem   = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);\r
-      KekCount  = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;\r
-      for (Index = 0; Index < KekCount; Index++) {\r
-        if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {\r
-          IsFound = TRUE;\r
-          break;\r
-        }\r
-        KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);\r
-      }\r
-    }\r
-    KekDataSize -= KekList->SignatureListSize;\r
-    KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);\r
-  }\r
-\r
-  if (!IsFound) {\r
-    //\r
-    // Signed key is not a trust one.\r
-    //\r
-    goto Done;\r
-  }\r
-\r
-  //\r
-  // Now, we found the corresponding security policy.\r
-  // Verify the data payload.\r
-  //\r
-  Rsa = RsaNew ();\r
-  if (Rsa == NULL) {\r
-    Status = FALSE;\r
-    goto Done;\r
-  }\r
-\r
-  //\r
-  // Set RSA Key Components.\r
-  // NOTE: Only N and E are needed to be set as RSA public key for signature verification.\r
-  //\r
-  Status = RsaSetKey (Rsa, RsaKeyN, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE);\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));\r
-  if (!Status) {\r
-    goto Done;\r
-  }\r
-  //\r
-  // Verify the signature.\r
-  //\r
-  Status = RsaPkcs1Verify (\r
-             Rsa,\r
-             mImageDigest,\r
-             mImageDigestSize,\r
-             CertBlock->Signature,\r
-             EFI_CERT_TYPE_RSA2048_SHA256_SIZE\r
-             );\r
-\r
-Done:\r
-  if (KekList != NULL) {\r
-    FreePool (KekList);\r
-  }\r
-  if (Rsa != NULL ) {\r
-    RsaFree (Rsa);\r
-  }\r
-  if (Status) {\r
+  if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {\r
     return EFI_SUCCESS;\r
   } else {\r
     return EFI_SECURITY_VIOLATION;\r
@@ -1062,22 +1010,28 @@ Done:
   Executables from FV is bypass, so pass in AuthenticationStatus is ignored.\r
 \r
   The image verification process is:\r
-    Is the Image signed?\r
-      If yes,\r
-        Does the image verify against a certificate (root or intermediate) in the allowed db?\r
-          Run it\r
-        Image verification fail\r
-          Is the Image's Hash not in forbidden database and the Image's Hash in allowed db?\r
-            Run it\r
-      If no,\r
-        Is the Image's Hash in the forbidden database (DBX)?\r
-          if yes,\r
-            Error out\r
-        Is the Image's Hash in the allowed database (DB)?\r
-          If yes,\r
-            Run it\r
-          If no,\r
-            Error out\r
+    If the image is signed,\r
+      If the image's certificate verifies against a certificate (root or intermediate) in the allowed \r
+      database (DB) and not in the forbidden database (DBX), the certificate verification is passed.\r
+        If the image's hash digest is in DBX,\r
+          deny execution.\r
+        If not,\r
+          run it.\r
+      If the Image's certificate verification failed.\r
+        If the Image's Hash is in DB and not in DBX,\r
+          run it.\r
+        Otherwise,\r
+          deny execution.\r
+    Otherwise, the image is not signed,\r
+      Is the Image's Hash in DBX?\r
+        If yes, deny execution.\r
+        If not, is the Image's Hash in DB?\r
+          If yes, run it.\r
+          If not, deny execution.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF image is external input, so this function will validate its data structure\r
+  within this image buffer before use.\r
 \r
   @param[in]    AuthenticationStatus\r
                            This is the authentication status returned from the security\r
@@ -1086,19 +1040,23 @@ Done:
                            being dispatched. This will optionally be used for logging.\r
   @param[in]    FileBuffer File buffer matches the input file device path.\r
   @param[in]    FileSize   Size of File buffer matches the input file device path.\r
-\r
-  @retval EFI_SUCCESS            The file specified by File did authenticate, and the\r
-                                 platform policy dictates that the DXE Core may use File.\r
-  @retval EFI_INVALID_PARAMETER  Input argument is incorrect.\r
+  @param[in]    BootPolicy A boot policy that was used to call LoadImage() UEFI service.\r
+\r
+  @retval EFI_SUCCESS            The file specified by DevicePath and non-NULL\r
+                                 FileBuffer did authenticate, and the platform policy dictates\r
+                                 that the DXE Foundation may use the file.\r
+  @retval EFI_SUCCESS            The device path specified by NULL device path DevicePath\r
+                                 and non-NULL FileBuffer did authenticate, and the platform\r
+                                 policy dictates that the DXE Foundation may execute the image in\r
+                                 FileBuffer.\r
   @retval EFI_OUT_RESOURCE       Fail to allocate memory.\r
   @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and\r
                                  the platform policy dictates that File should be placed\r
-                                 in the untrusted state. A file may be promoted from\r
-                                 the untrusted to the trusted state at a future time\r
-                                 with a call to the Trust() DXE Service.\r
-  @retval EFI_ACCESS_DENIED      The file specified by File did not authenticate, and\r
-                                 the platform policy dictates that File should not be\r
-                                 used for any purpose.\r
+                                 in the untrusted state. The image has been added to the file\r
+                                 execution table.\r
+  @retval EFI_ACCESS_DENIED      The file specified by File and FileBuffer did not\r
+                                 authenticate, and the platform policy dictates that the DXE\r
+                                 Foundation many not use File.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1107,29 +1065,35 @@ DxeImageVerificationHandler (
   IN  UINT32                           AuthenticationStatus,\r
   IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,\r
   IN  VOID                             *FileBuffer,\r
-  IN  UINTN                            FileSize\r
+  IN  UINTN                            FileSize,\r
+  IN  BOOLEAN                          BootPolicy\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  UINT16                      Magic;\r
-  EFI_IMAGE_DOS_HEADER        *DosHdr;\r
-  EFI_STATUS                  VerifyStatus;\r
-  UINT8                       *SetupMode;\r
-  EFI_SIGNATURE_LIST          *SignatureList;\r
-  UINTN                       SignatureListSize;\r
-  EFI_SIGNATURE_DATA          *Signature;\r
-  EFI_IMAGE_EXECUTION_ACTION  Action;\r
-  WIN_CERTIFICATE             *WinCertificate;\r
-  UINT32                      Policy;\r
-  UINT8                       *SecureBootEnable;\r
-\r
-  if (File == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+  EFI_STATUS                           Status;\r
+  UINT16                               Magic;\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  EFI_STATUS                           VerifyStatus;\r
+  EFI_SIGNATURE_LIST                   *SignatureList;\r
+  UINTN                                SignatureListSize;\r
+  EFI_SIGNATURE_DATA                   *Signature;\r
+  EFI_IMAGE_EXECUTION_ACTION           Action;\r
+  WIN_CERTIFICATE                      *WinCertificate;\r
+  UINT32                               Policy;\r
+  UINT8                                *SecureBoot;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;\r
+  UINT32                               NumberOfRvaAndSizes;\r
+  UINT32                               CertSize;\r
+  WIN_CERTIFICATE_EFI_PKCS             *PkcsCertData;\r
+  WIN_CERTIFICATE_UEFI_GUID            *WinCertUefiGuid;\r
+  UINT8                                *AuthData;\r
+  UINTN                                AuthDataSize;\r
+  EFI_IMAGE_DATA_DIRECTORY             *SecDataDir;\r
 \r
   SignatureList     = NULL;\r
   SignatureListSize = 0;\r
   WinCertificate    = NULL;\r
+  SecDataDir        = NULL;\r
+  PkcsCertData      = NULL;\r
   Action            = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;\r
   Status            = EFI_ACCESS_DENIED;\r
   //\r
@@ -1166,49 +1130,51 @@ DxeImageVerificationHandler (
     return EFI_ACCESS_DENIED;\r
   }\r
 \r
-  SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid);\r
-  //\r
-  // Skip verification if SecureBootEnable variable doesn't exist.\r
-  //\r
-  if (SecureBootEnable == NULL) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
+  GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBoot, NULL);\r
   //\r
-  // Skip verification if SecureBootEnable is disabled.\r
+  // Skip verification if SecureBoot variable doesn't exist.\r
   //\r
-  if (*SecureBootEnable == SECURE_BOOT_DISABLE) {\r
-    FreePool (SecureBootEnable);\r
+  if (SecureBoot == NULL) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  SetupMode = GetEfiGlobalVariable (EFI_SETUP_MODE_NAME);\r
-\r
   //\r
-  // SetupMode doesn't exist means no AuthVar driver is dispatched,\r
-  // skip verification.\r
+  // Skip verification if SecureBoot is disabled.\r
   //\r
-  if (SetupMode == NULL) {\r
+  if (*SecureBoot == SECURE_BOOT_MODE_DISABLE) {\r
+    FreePool (SecureBoot);\r
     return EFI_SUCCESS;\r
   }\r
+  FreePool (SecureBoot);\r
 \r
-  //\r
-  // If platform is in SETUP MODE, skip verification.\r
-  //\r
-  if (*SetupMode == SETUP_MODE) {\r
-    FreePool (SetupMode);\r
-    return EFI_SUCCESS;\r
-  }\r
   //\r
   // Read the Dos header.\r
   //\r
   if (FileBuffer == NULL) {\r
-    FreePool (SetupMode);\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   mImageBase  = (UINT8 *) FileBuffer;\r
   mImageSize  = FileSize;\r
-  DosHdr      = (EFI_IMAGE_DOS_HEADER *) mImageBase;\r
+\r
+  ZeroMem (&ImageContext, sizeof (ImageContext));\r
+  ImageContext.Handle    = (VOID *) FileBuffer;\r
+  ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) DxeImageVerificationLibImageRead;\r
+\r
+  //\r
+  // Get information about the image being loaded\r
+  //\r
+  Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // The information can't be got from the invalid PeImage\r
+    //\r
+    goto Done;\r
+  }\r
+\r
+  Status = EFI_ACCESS_DENIED;\r
+\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER *) mImageBase;\r
   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
     //\r
     // DOS image header is present,\r
@@ -1226,37 +1192,43 @@ DxeImageVerificationHandler (
     //\r
     // It is not a valid Pe/Coff file.\r
     //\r
-    return EFI_ACCESS_DENIED;\r
+    goto Done;\r
   }\r
 \r
-  Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-    //\r
-    // Use PE32 offset.\r
+  if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     //\r
-    mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
-  } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value \r
+    //       in the PE/COFF Header. If the MachineType is Itanium(IA64) and the \r
+    //       Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+    //       then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
     //\r
-    // Use PE32+ offset.\r
-    //\r
-    mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+    Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
   } else {\r
     //\r
-    // Invalid header magic number.\r
+    // Get the magic value from the PE/COFF Optional Header\r
     //\r
-    Status       = EFI_INVALID_PARAMETER;\r
-    goto Done;\r
+    Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
   }\r
-\r
-  if (mSecDataDir->VirtualAddress >= mImageSize) {\r
+  \r
+  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     //\r
-    // Sanity check to see if this file is corrupted.\r
+    // Use PE32 offset.\r
     //\r
-    Status       = EFI_INVALID_PARAMETER;\r
-    goto Done;\r
+    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+    }        \r
+  } else {\r
+    //\r
+    // Use PE32+ offset.\r
+    //\r
+    NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+    }\r
   }\r
 \r
-  if (mSecDataDir->Size == 0) {\r
+  if ((SecDataDir == NULL) || ((SecDataDir != NULL) && (SecDataDir->Size == 0))) {\r
     //\r
     // This image is not signed.\r
     //\r
@@ -1268,8 +1240,6 @@ DxeImageVerificationHandler (
       //\r
       // Image Hash is in forbidden database (DBX).\r
       //\r
-      Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;\r
-      Status = EFI_ACCESS_DENIED;\r
       goto Done;\r
     }\r
 \r
@@ -1283,74 +1253,81 @@ DxeImageVerificationHandler (
     //\r
     // Image Hash is not found in both forbidden and allowed database.\r
     //\r
-    Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;\r
-    Status = EFI_ACCESS_DENIED;\r
     goto Done;\r
   }\r
 \r
   //\r
   // Verify signature of executables.\r
   //\r
-  WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress);\r
+  WinCertificate = (WIN_CERTIFICATE *) (mImageBase + SecDataDir->VirtualAddress);\r
 \r
-  switch (WinCertificate->wCertificateType) {\r
+  CertSize = sizeof (WIN_CERTIFICATE);\r
 \r
-  case WIN_CERT_TYPE_EFI_GUID:\r
+  if ((SecDataDir->Size <= CertSize) || (SecDataDir->Size < WinCertificate->dwLength)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.\r
+  //\r
+  if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
     //\r
-    // Verify UEFI GUID type.\r
+    // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the \r
+    // Authenticode specification.\r
     //\r
-    if (!HashPeImage (HASHALG_SHA256)) {\r
+    PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;\r
+    if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) {\r
+      goto Done;\r
+    }\r
+    AuthData   = PkcsCertData->CertData;\r
+    AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);\r
+    \r
+    Status = HashPeImageByType (AuthData, AuthDataSize);\r
+    if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
 \r
-    VerifyStatus = VerifyCertUefiGuid ();\r
-    break;\r
-\r
-  case WIN_CERT_TYPE_PKCS_SIGNED_DATA:\r
+    VerifyStatus = VerifyCertPkcsSignedData (AuthData, AuthDataSize);\r
+  } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {\r
     //\r
-    // Verify Pkcs signed data type.\r
+    // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is described in UEFI Spec.\r
     //\r
-    Status    = HashPeImageByType();\r
+    WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;\r
+    if (!CompareGuid(&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid) ||\r
+        (WinCertUefiGuid->Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData))) {\r
+      goto Done;\r
+    }\r
+    AuthData = WinCertUefiGuid->CertData;\r
+    AuthDataSize = WinCertUefiGuid->Hdr.dwLength - OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);\r
+    \r
+    Status = HashPeImageByType (AuthData, AuthDataSize);\r
     if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
+    VerifyStatus = VerifyCertPkcsSignedData (AuthData, AuthDataSize);\r
+  } else {\r
+    goto Done;\r
+  }\r
 \r
-    VerifyStatus = VerifyCertPkcsSignedData ();\r
-\r
+  if (!EFI_ERROR (VerifyStatus)) {\r
     //\r
-    // For image verification against enrolled certificate(root or intermediate),\r
-    // no need to check image's hash in the allowed database.\r
+    // Verification is passed.\r
+    // Continue to check the image digest in signature database.\r
     //\r
-    if (!EFI_ERROR (VerifyStatus)) {\r
-      if (!IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\r
-        return EFI_SUCCESS;\r
-      }\r
+    if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\r
+      //\r
+      // Executable signature verification passes, but is found in forbidden signature database.\r
+      //\r
+      Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;\r
+      Status = EFI_ACCESS_DENIED;\r
+    } else {\r
+      //\r
+      // For image verification against enrolled X.509 certificate(root or intermediate),\r
+      // no need to check image's hash in the allowed database.\r
+      //\r
+      return EFI_SUCCESS;\r
     }\r
-    break;\r
-\r
-  default:\r
-    Status = EFI_ACCESS_DENIED;\r
-    goto Done;\r
-  }\r
-  //\r
-  // Get image hash value as executable's signature.\r
-  //\r
-  SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;\r
-  SignatureList     = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignatureListSize);\r
-  if (SignatureList == NULL) {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto Done;\r
-  }\r
-  SignatureList->SignatureHeaderSize  = 0;\r
-  SignatureList->SignatureListSize    = (UINT32) SignatureListSize;\r
-  SignatureList->SignatureSize        = (UINT32) mImageDigestSize;\r
-  CopyMem (&SignatureList->SignatureType, &mCertType, sizeof (EFI_GUID));\r
-  Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));\r
-  CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);\r
-  //\r
-  // Signature database check after verification.\r
-  //\r
-  if (EFI_ERROR (VerifyStatus)) {\r
+  } else {\r
     //\r
     // Verification failure.\r
     //\r
@@ -1365,24 +1342,24 @@ DxeImageVerificationHandler (
       Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;\r
       Status = EFI_ACCESS_DENIED;\r
     }\r
-  } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, Signature->SignatureData, &mCertType, mImageDigestSize)) {\r
-    //\r
-    // Executable signature verification passes, but is found in forbidden signature database.\r
-    //\r
-    Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;\r
-    Status = EFI_ACCESS_DENIED;\r
-  } else if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, Signature->SignatureData, &mCertType, mImageDigestSize)) {\r
-    //\r
-    // Executable signature is found in authorized signature database.\r
-    //\r
-    Status = EFI_SUCCESS;\r
-  } else {\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
     //\r
-    // Executable signature verification passes, but cannot be found in authorized signature database.\r
-    // Get platform policy to determine the action.\r
+    // Get image hash value as executable's signature.\r
     //\r
-    Action = EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED;\r
-    Status = ImageAuthorization (Policy);\r
+    SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;\r
+    SignatureList     = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignatureListSize);\r
+    if (SignatureList == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+    SignatureList->SignatureHeaderSize  = 0;\r
+    SignatureList->SignatureListSize    = (UINT32) SignatureListSize;\r
+    SignatureList->SignatureSize        = (UINT32) mImageDigestSize;\r
+    CopyMem (&SignatureList->SignatureType, &mCertType, sizeof (EFI_GUID));\r
+    Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));\r
+    CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);\r
   }\r
 \r
 Done:\r
@@ -1391,14 +1368,13 @@ Done:
     // Policy decides to defer or reject the image; add its information in image executable information table.\r
     //\r
     AddImageExeInfo (Action, NULL, File, SignatureList, SignatureListSize);\r
+    Status = EFI_SECURITY_VIOLATION;\r
   }\r
 \r
   if (SignatureList != NULL) {\r
     FreePool (SignatureList);\r
   }\r
 \r
-  FreePool (SetupMode);\r
-\r
   return Status;\r
 }\r
 \r
@@ -1431,7 +1407,7 @@ VariableWriteCallBack (
   // If this library is built-in, it means firmware has capability to perform\r
   // driver signing verification.\r
   //\r
-  SecureBootModePtr = GetEfiGlobalVariable (EFI_SECURE_BOOT_MODE_NAME);\r
+  GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID**)&SecureBootModePtr, NULL);\r
   if (SecureBootModePtr == NULL) {\r
     SecureBootMode   = SECURE_BOOT_MODE_DISABLE;\r
     //\r
@@ -1477,7 +1453,7 @@ DxeImageVerificationLibConstructor (
     &Registration\r
     );\r
 \r
-  return RegisterSecurityHandler (\r
+  return RegisterSecurity2Handler (\r
           DxeImageVerificationHandler,\r
           EFI_AUTH_OPERATION_VERIFY_IMAGE | EFI_AUTH_OPERATION_IMAGE_REQUIRED\r
           );\r