]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
Add PI1.2.1 SAP2 support and UEFI231B mantis 896
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / DxeImageVerificationLib.c
index 91977522a9138cd9c751f543d22c0def0a553ce1..402540eb1b2bd4469f42bffcc5b6975537848ea5 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,15 +25,23 @@ 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
-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
+// Information on current PE/COFF image\r
+//\r
+UINTN                               mImageSize;\r
+UINT8                               *mImageBase       = NULL;\r
+UINT8                               mImageDigest[MAX_DIGEST_SIZE];\r
+UINTN                               mImageDigestSize;\r
+\r
 //\r
 // Notify string for authorization UI.\r
 //\r
@@ -54,6 +73,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
@@ -185,6 +252,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 +278,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 +319,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 +349,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 +368,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 +472,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 +530,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,6 +577,10 @@ 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
   @retval EFI_UNSUPPORTED             Hash algorithm is not supported.\r
   @retval EFI_SUCCESS                 Hash successfully.\r
 \r
@@ -475,6 +595,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 +610,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
@@ -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
@@ -848,14 +930,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
+                           PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr),\r
                            RootCert,\r
                            RootCertSize,\r
                            mImageDigest,\r
@@ -904,14 +986,7 @@ 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
+  // 2: 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
@@ -920,139 +995,6 @@ VerifyCertPkcsSignedData (
   }\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
-  //\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
-    return EFI_SUCCESS;\r
-  } else {\r
-    return EFI_SECURITY_VIOLATION;\r
-  }\r
-}\r
-\r
 /**\r
   Provide verification service for signed images, which include both signature validation\r
   and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and\r
@@ -1062,22 +1004,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
@@ -1110,18 +1058,20 @@ 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
+  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
 \r
   if (File == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1166,49 +1116,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 +1178,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
-    //\r
-    // Use PE32+ offset.\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
-    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
+      mSecDataDir = (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
+      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 +1226,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 +1239,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,64 +1247,45 @@ DxeImageVerificationHandler (
   //\r
   WinCertificate = (WIN_CERTIFICATE *) (mImageBase + mSecDataDir->VirtualAddress);\r
 \r
-  switch (WinCertificate->wCertificateType) {\r
-\r
-  case WIN_CERT_TYPE_EFI_GUID:\r
-    //\r
-    // Verify UEFI GUID type.\r
-    //\r
-    if (!HashPeImage (HASHALG_SHA256)) {\r
-      goto Done;\r
-    }\r
+  CertSize = sizeof (WIN_CERTIFICATE);\r
 \r
-    VerifyStatus = VerifyCertUefiGuid ();\r
-    break;\r
+  if ((mSecDataDir->Size <= CertSize) || (mSecDataDir->Size < WinCertificate->dwLength)) {\r
+    goto Done;\r
+  }\r
 \r
-  case WIN_CERT_TYPE_PKCS_SIGNED_DATA:\r
+  if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
     //\r
     // Verify Pkcs signed data type.\r
     //\r
-    Status    = HashPeImageByType();\r
+    Status = HashPeImageByType();\r
     if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
-\r
+    \r
     VerifyStatus = VerifyCertPkcsSignedData ();\r
+  } else {\r
+    goto Done;\r
+  }\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 +1300,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
@@ -1397,8 +1332,6 @@ Done:
     FreePool (SignatureList);\r
   }\r
 \r
-  FreePool (SetupMode);\r
-\r
   return Status;\r
 }\r
 \r
@@ -1431,7 +1364,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