1. Enhance DxeImageVerificationLib to avoid some corrupted input.
authorhhuan13 <hhuan13@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 21 Sep 2011 05:23:55 +0000 (05:23 +0000)
committerhhuan13 <hhuan13@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 21 Sep 2011 05:23:55 +0000 (05:23 +0000)
Signed-off-by: hhuan13
Reviewed-by: qlong
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12399 6f19259b-4bc3-4df7-8a09-765794883524

SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c

index 148dbd5a89e9dd56e4bfca5a9c6af7b701824c4b..dab35d5f6c2edfb4e0a6a36bbc2fd6f138d0edb4 100644 (file)
@@ -207,7 +207,9 @@ HashPeImage (
   EFI_IMAGE_SECTION_HEADER  *SectionHeader;\r
   UINTN                     Index;\r
   UINTN                     Pos;\r
-\r
+  UINTN                     SumOfSectionBytes;\r
+  EFI_IMAGE_SECTION_HEADER  *SectionCache;  \r
+  \r
   HashCtx       = NULL;\r
   SectionHeader = NULL;\r
   Status        = FALSE;\r
@@ -234,7 +236,9 @@ HashPeImage (
   CtxSize   = mHash[HashAlg].GetContextSize();\r
   \r
   HashCtx = AllocatePool (CtxSize);\r
-  ASSERT (HashCtx != NULL);\r
+  if (HashCtx == NULL) {\r
+    return FALSE;\r
+  }\r
 \r
   // 1.  Load the image header into memory.\r
 \r
@@ -259,11 +263,17 @@ HashPeImage (
     // Use PE32 offset.\r
     //\r
     HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
-  } else {\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
+  } else {\r
+    //\r
+    // Invalid header magic number.\r
+    //\r
+    Status = FALSE;\r
+    goto Done;\r
   }\r
 \r
   Status  = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize);\r
@@ -330,6 +340,29 @@ HashPeImage (
     SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders;\r
   }\r
 \r
+\r
+  Section = (EFI_IMAGE_SECTION_HEADER *) (\r
+               mImageBase +\r
+               mPeCoffHeaderOffset +\r
+               sizeof (UINT32) +\r
+               sizeof (EFI_IMAGE_FILE_HEADER) +\r
+               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
@@ -337,20 +370,16 @@ HashPeImage (
   //     IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.\r
   //\r
   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections);\r
-  ASSERT (SectionHeader != NULL);\r
+  if (SectionHeader == NULL) {\r
+    Status = FALSE;\r
+    goto Done;\r
+  }\r
   //\r
   // 12.  Using the 'PointerToRawData' in the referenced section headers as\r
   //      a key, arrange the elements in the table in ascending order. In other\r
   //      words, sort the section headers according to the disk-file offset of\r
   //      the section.\r
   //\r
-  Section = (EFI_IMAGE_SECTION_HEADER *) (\r
-               mImageBase +\r
-               mPeCoffHeaderOffset +\r
-               sizeof (UINT32) +\r
-               sizeof (EFI_IMAGE_FILE_HEADER) +\r
-               mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader\r
-               );\r
   for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) {\r
     Pos = Index;\r
     while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) {\r
@@ -532,7 +561,6 @@ AddImageExeInfo (
   IN       UINTN                            SignatureSize\r
   )\r
 {\r
-  EFI_STATUS                      Status;\r
   EFI_IMAGE_EXECUTION_INFO_TABLE  *ImageExeInfoTable;\r
   EFI_IMAGE_EXECUTION_INFO_TABLE  *NewImageExeInfoTable;\r
   EFI_IMAGE_EXECUTION_INFO        *ImageExeInfoEntry;\r
@@ -541,12 +569,15 @@ AddImageExeInfo (
   UINTN                           NameStringLen;\r
   UINTN                           DevicePathSize;\r
 \r
-  ASSERT (DevicePath != NULL);\r
   ImageExeInfoTable     = NULL;\r
   NewImageExeInfoTable  = NULL;\r
   ImageExeInfoEntry     = NULL;\r
   NameStringLen         = 0;\r
 \r
+  if (DevicePath == NULL) {\r
+    return ;\r
+  }\r
+  \r
   if (Name != NULL) {\r
     NameStringLen = StrSize (Name);\r
   }\r
@@ -570,7 +601,9 @@ AddImageExeInfo (
   DevicePathSize            = GetDevicePathSize (DevicePath);\r
   NewImageExeInfoEntrySize  = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;\r
   NewImageExeInfoTable      = (EFI_IMAGE_EXECUTION_INFO_TABLE *) AllocateRuntimePool (ImageExeInfoTableSize + NewImageExeInfoEntrySize);\r
-  ASSERT (NewImageExeInfoTable != NULL);\r
+  if (NewImageExeInfoTable == NULL) {\r
+    return ;\r
+  }\r
 \r
   if (ImageExeInfoTable != NULL) {\r
     CopyMem (NewImageExeInfoTable, ImageExeInfoTable, ImageExeInfoTableSize);\r
@@ -603,8 +636,8 @@ AddImageExeInfo (
   //\r
   // Update/replace the image execution table.\r
   //\r
-  Status = gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);\r
-  ASSERT_EFI_ERROR (Status);\r
+  gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) NewImageExeInfoTable);\r
+  \r
   //\r
   // Free Old table data!\r
   //\r
@@ -707,7 +740,9 @@ IsSignatureFoundInDatabase (
   }\r
 \r
   Data = (UINT8 *) AllocateZeroPool (DataSize);\r
-  ASSERT (Data != NULL);\r
+  if (Data == NULL) {\r
+    return FALSE;\r
+  }\r
 \r
   Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);\r
   if (EFI_ERROR (Status)) {\r
@@ -755,7 +790,7 @@ Done:
 \r
   @retval EFI_SUCCESS                 Image pass verification.\r
   @retval EFI_SECURITY_VIOLATION      Image fail verification.\r
-  @retval other error value\r
+  @retval EFI_OUT_OF_RESOURCE         Fail to allocate memory.\r
 \r
 **/\r
 EFI_STATUS \r
@@ -769,13 +804,15 @@ VerifyCertPkcsSignedData (
   EFI_SIGNATURE_LIST        *CertList;\r
   EFI_SIGNATURE_DATA        *Cert;\r
   UINTN                     DataSize;\r
-  UINT8                     *Data;\r
+  UINT8                     *KekData;\r
+  UINT8                     *DbData;\r
   UINT8                     *RootCert;\r
   UINTN                     RootCertSize;\r
   UINTN                     Index;\r
   UINTN                     CertCount;\r
 \r
-  Data                   = NULL;\r
+  KekData                = NULL;\r
+  DbData                 = NULL;\r
   CertList               = NULL;\r
   Cert                   = NULL;\r
   RootCert               = NULL;\r
@@ -789,10 +826,12 @@ VerifyCertPkcsSignedData (
   DataSize = 0;\r
   Status   = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    Data = (UINT8 *)AllocateZeroPool (DataSize);\r
-    ASSERT (Data != NULL);\r
+    KekData = (UINT8 *)AllocateZeroPool (DataSize);\r
+    if (KekData == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
 \r
-    Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, (VOID *)Data);\r
+    Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, (VOID *)KekData);\r
     if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
@@ -800,7 +839,7 @@ VerifyCertPkcsSignedData (
     //\r
     // Find Cert Enrolled in KEK database to verify the signature in pkcs7 signed data.\r
     // \r
-    CertList = (EFI_SIGNATURE_LIST *) Data;\r
+    CertList = (EFI_SIGNATURE_LIST *) KekData;\r
     while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
       if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
         Cert          = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
@@ -843,10 +882,12 @@ VerifyCertPkcsSignedData (
   DataSize = 0;\r
   Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    Data = (UINT8 *)AllocateZeroPool (DataSize);\r
-    ASSERT (Data != NULL);\r
+    DbData = (UINT8 *)AllocateZeroPool (DataSize);\r
+    if (DbData == NULL) {\r
+      goto Done;\r
+    }\r
 \r
-    Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *)Data);\r
+    Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *)DbData);\r
     if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
@@ -854,7 +895,7 @@ VerifyCertPkcsSignedData (
     //\r
     // Find Cert Enrolled in DB database to verify the signature in pkcs7 signed data.\r
     // \r
-    CertList = (EFI_SIGNATURE_LIST *) Data;\r
+    CertList = (EFI_SIGNATURE_LIST *) DbData;\r
     while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
       if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
         Cert          = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
@@ -890,8 +931,12 @@ VerifyCertPkcsSignedData (
   }\r
 \r
 Done:\r
-  if (Data != NULL) {\r
-    FreePool (Data);\r
+  if (KekData != NULL) {\r
+    FreePool (KekData);\r
+  }\r
+\r
+  if (DbData != NULL) {\r
+    FreePool (DbData);\r
   }\r
 \r
   if (VerifyStatus) {\r
@@ -992,7 +1037,11 @@ VerifyCertUefiGuid (
   // Verify the data payload.\r
   //\r
   Rsa = RsaNew ();\r
-  ASSERT (Rsa != NULL);\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
@@ -1048,7 +1097,8 @@ Done:
 \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  File is NULL.\r
+  @retval EFI_INVALID_PARAMETER  Input argument is incorrect.\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
@@ -1143,7 +1193,10 @@ DxeImageVerificationHandler (
   //\r
   // Read the Dos header.\r
   //\r
-  ASSERT (FileBuffer != NULL);\r
+  if (FileBuffer == NULL) {\r
+    FreePool (SetupMode);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
   mImageBase  = (UINT8 *) FileBuffer;\r
   mImageSize  = FileSize;\r
   DosHdr      = (EFI_IMAGE_DOS_HEADER *) (mImageBase);\r
@@ -1173,11 +1226,25 @@ DxeImageVerificationHandler (
     // Use PE32 offset.\r
     //\r
     mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *)&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
-  } else {\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
+  } 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
+    //\r
+    Status       = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
   }\r
 \r
   if (mSecDataDir->Size == 0) {\r
@@ -1233,7 +1300,10 @@ DxeImageVerificationHandler (
   //\r
   SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;\r
   SignatureList     = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignatureListSize);\r
-  ASSERT (SignatureList != NULL);\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