]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
Enhance GPT measurement to be able to handle different partition entry size.
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / DxeImageVerificationLib.c
index 91977522a9138cd9c751f543d22c0def0a553ce1..79d226125107506e380f16b1d86e2e9249858bea 100644 (file)
@@ -1,7 +1,7 @@
 /** @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
+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
@@ -54,6 +54,50 @@ 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
+  @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
@@ -207,8 +251,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,6 +292,7 @@ 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
@@ -263,11 +308,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 +327,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 +431,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 +489,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
@@ -475,6 +550,10 @@ HashPeImageByType (
 \r
   PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->VirtualAddress);\r
 \r
+  if (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   for (Index = 0; Index < HASHALG_MAX; Index++) {\r
     //\r
     // Check the Hash algorithm in PE/COFF Authenticode.\r
@@ -486,7 +565,19 @@ 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 ((*(PkcsCertData->CertData + 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 (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32 + mHash[Index].OidLength) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
     if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) {\r
       break;\r
     }\r
@@ -855,7 +946,7 @@ IsPkcsSignedDataVerifiedBySignatureList (
           //\r
           VerifyStatus = AuthenticodeVerify (\r
                            PkcsCertData->CertData,\r
-                           mSecDataDir->Size - sizeof(PkcsCertData->Hdr),\r
+                           PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr),\r
                            RootCert,\r
                            RootCertSize,\r
                            mImageDigest,\r
@@ -974,7 +1065,7 @@ VerifyCertUefiGuid (
   //\r
   // Get KEK database variable.\r
   //\r
-  KekList = GetEfiGlobalVariable (EFI_KEY_EXCHANGE_KEY_NAME);\r
+  GetEfiGlobalVariable2 (EFI_KEY_EXCHANGE_KEY_NAME, (VOID**)&KekList, NULL);\r
   if (KekList == NULL) {\r
     return EFI_SECURITY_VIOLATION;\r
   }\r
@@ -1110,18 +1201,21 @@ DxeImageVerificationHandler (
   IN  UINTN                            FileSize\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
+  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
+  PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;\r
+  UINT32                               NumberOfRvaAndSizes;\r
+  UINT32                               CertSize;\r
 \r
   if (File == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1166,7 +1260,7 @@ DxeImageVerificationHandler (
     return EFI_ACCESS_DENIED;\r
   }\r
 \r
-  SecureBootEnable = GetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid);\r
+  GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL);\r
   //\r
   // Skip verification if SecureBootEnable variable doesn't exist.\r
   //\r
@@ -1182,7 +1276,9 @@ DxeImageVerificationHandler (
     return EFI_SUCCESS;\r
   }\r
 \r
-  SetupMode = GetEfiGlobalVariable (EFI_SETUP_MODE_NAME);\r
+  FreePool (SecureBootEnable);\r
+\r
+  GetEfiGlobalVariable2 (EFI_SETUP_MODE_NAME, (VOID**)&SetupMode, NULL);\r
 \r
   //\r
   // SetupMode doesn't exist means no AuthVar driver is dispatched,\r
@@ -1199,16 +1295,37 @@ DxeImageVerificationHandler (
     FreePool (SetupMode);\r
     return EFI_SUCCESS;\r
   }\r
+\r
+  FreePool (SetupMode);\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,7 +1343,7 @@ 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
@@ -1234,29 +1351,21 @@ DxeImageVerificationHandler (
     //\r
     // Use PE32 offset.\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
-    //\r
-    // Use PE32+ offset.\r
-    //\r
-    mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+    NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+    }        \r
   } else {\r
     //\r
-    // Invalid header magic number.\r
-    //\r
-    Status       = EFI_INVALID_PARAMETER;\r
-    goto Done;\r
-  }\r
-\r
-  if (mSecDataDir->VirtualAddress >= mImageSize) {\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.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
+      mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
+    }\r
   }\r
 \r
-  if (mSecDataDir->Size == 0) {\r
+  if ((mSecDataDir == NULL) || ((mSecDataDir != NULL) && (mSecDataDir->Size == 0))) {\r
     //\r
     // This image is not signed.\r
     //\r
@@ -1268,8 +1377,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,8 +1390,6 @@ 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
@@ -1293,9 +1398,20 @@ DxeImageVerificationHandler (
   //\r
   WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress);\r
 \r
+  CertSize = sizeof (WIN_CERTIFICATE);\r
+\r
+  if ((mSecDataDir->Size <= CertSize) || (mSecDataDir->Size < WinCertificate->dwLength)) {\r
+    goto Done;\r
+  }\r
+\r
   switch (WinCertificate->wCertificateType) {\r
 \r
   case WIN_CERT_TYPE_EFI_GUID:\r
+    CertSize = sizeof (WIN_CERTIFICATE_UEFI_GUID) + sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256) - sizeof (UINT8);\r
+    if (WinCertificate->dwLength < CertSize) {\r
+      goto Done;\r
+    }\r
+\r
     //\r
     // Verify UEFI GUID type.\r
     //\r
@@ -1310,7 +1426,7 @@ DxeImageVerificationHandler (
     //\r
     // Verify Pkcs signed data type.\r
     //\r
-    Status    = HashPeImageByType();\r
+    Status = HashPeImageByType();\r
     if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
@@ -1329,7 +1445,6 @@ DxeImageVerificationHandler (
     break;\r
 \r
   default:\r
-    Status = EFI_ACCESS_DENIED;\r
     goto Done;\r
   }\r
   //\r
@@ -1397,8 +1512,6 @@ Done:
     FreePool (SignatureList);\r
   }\r
 \r
-  FreePool (SetupMode);\r
-\r
   return Status;\r
 }\r
 \r
@@ -1431,7 +1544,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