]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
Add the missed local variable initialization to remove the possible warning.
[mirror_edk2.git] / SecurityPkg / Library / DxeImageVerificationLib / DxeImageVerificationLib.c
index 3324dba0af862dfad49d2e8e6cc5d93054363208..a713d0d4ae1949e23622a3da29b8d6294c3083ff 100644 (file)
@@ -12,7 +12,7 @@
   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 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2015, 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
@@ -769,7 +769,7 @@ AddImageExeInfo (
   }\r
 \r
   DevicePathSize            = GetDevicePathSize (DevicePath);\r
-  NewImageExeInfoEntrySize  = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;\r
+  NewImageExeInfoEntrySize  = sizeof (EFI_IMAGE_EXECUTION_INFO) - sizeof (EFI_SIGNATURE_LIST) + NameStringLen + DevicePathSize + SignatureSize;\r
   NewImageExeInfoTable      = (EFI_IMAGE_EXECUTION_INFO_TABLE *) AllocateRuntimePool (ImageExeInfoTableSize + NewImageExeInfoEntrySize);\r
   if (NewImageExeInfoTable == NULL) {\r
     return ;\r
@@ -841,7 +841,7 @@ IsCertHashFoundInDatabase (
   )\r
 {\r
   BOOLEAN             IsFound;\r
-  EFI_STATUS          Status;\r
+  BOOLEAN             Status;\r
   EFI_SIGNATURE_LIST  *DbxList;\r
   UINTN               DbxSize;\r
   EFI_SIGNATURE_DATA  *CertHash;\r
@@ -852,6 +852,8 @@ IsCertHashFoundInDatabase (
   UINT8               CertDigest[MAX_DIGEST_SIZE];\r
   UINT8               *DbxCertHash;\r
   UINTN               SiglistHeaderSize;\r
+  UINT8               *TBSCert;\r
+  UINTN               TBSCertSize;\r
 \r
   IsFound  = FALSE;\r
   DbxList  = SignatureList;\r
@@ -859,7 +861,16 @@ IsCertHashFoundInDatabase (
   HashCtx  = NULL;\r
   HashAlg  = HASHALG_MAX;\r
 \r
-  ASSERT (RevocationTime != NULL);\r
+  if ((RevocationTime == NULL) || (DbxList == NULL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Retrieve the TBSCertificate from the X.509 Certificate.\r
+  //\r
+  if (!X509GetTBSCert (Certificate, CertSize, &TBSCert, &TBSCertSize)) {\r
+    return FALSE;\r
+  }\r
 \r
   while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {\r
     //\r
@@ -878,7 +889,7 @@ IsCertHashFoundInDatabase (
     }\r
 \r
     //\r
-    // Calculate the hash value of current db certificate for comparision.\r
+    // Calculate the hash value of current TBSCertificate for comparision.\r
     //\r
     if (mHash[HashAlg].GetContextSize == NULL) {\r
       goto Done;\r
@@ -892,7 +903,7 @@ IsCertHashFoundInDatabase (
     if (!Status) {\r
       goto Done;\r
     }\r
-    Status = mHash[HashAlg].HashUpdate (HashCtx, Certificate, CertSize);\r
+    Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);\r
     if (!Status) {\r
       goto Done;\r
     }\r
@@ -1132,15 +1143,16 @@ PassTimestampCheck (
   //\r
   DbtDataSize = 0;\r
   Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, NULL);\r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    DbtData = (UINT8 *) AllocateZeroPool (DbtDataSize);\r
-    if (DbtData == NULL) {\r
-      goto Done;\r
-    }\r
-    Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, (VOID *) DbtData);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Done;\r
-    }\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    goto Done;\r
+  }\r
+  DbtData = (UINT8 *) AllocateZeroPool (DbtDataSize);\r
+  if (DbtData == NULL) {\r
+    goto Done;\r
+  }\r
+  Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, (VOID *) DbtData);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
   }\r
 \r
   CertList = (EFI_SIGNATURE_LIST *) DbtData;\r
@@ -1202,6 +1214,12 @@ IsForbiddenByDbx (
   BOOLEAN                   IsForbidden;\r
   UINT8                     *Data;\r
   UINTN                     DataSize;\r
+  EFI_SIGNATURE_LIST        *CertList;\r
+  UINTN                     CertListSize;\r
+  EFI_SIGNATURE_DATA        *CertData;\r
+  UINT8                     *RootCert;\r
+  UINTN                     RootCertSize;\r
+  UINTN                     CertCount;\r
   UINTN                     Index;\r
   UINT8                     *CertBuffer;\r
   UINTN                     BufferLength;\r
@@ -1218,6 +1236,10 @@ IsForbiddenByDbx (
   //\r
   IsForbidden       = FALSE;\r
   Data              = NULL;\r
+  CertList          = NULL;\r
+  CertData          = NULL;\r
+  RootCert          = NULL;\r
+  RootCertSize      = 0;\r
   Cert              = NULL;\r
   CertBuffer        = NULL;\r
   BufferLength      = 0;\r
@@ -1229,18 +1251,65 @@ IsForbiddenByDbx (
   //\r
   DataSize = 0;\r
   Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    Data = (UINT8 *) AllocateZeroPool (DataSize);\r
-    if (Data == NULL) {\r
-      return IsForbidden;\r
-    }\r
-\r
-    Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    return IsForbidden;\r
+  }\r
+  Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+  if (Data == NULL) {\r
+    return IsForbidden;\r
   }\r
+\r
+  Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);\r
   if (EFI_ERROR (Status)) {\r
     return IsForbidden;\r
   }\r
 \r
+  //\r
+  // Verify image signature with RAW X509 certificates in DBX database.\r
+  // If passed, the image will be forbidden.\r
+  //\r
+  CertList     = (EFI_SIGNATURE_LIST *) Data;\r
+  CertListSize = DataSize;\r
+  while ((CertListSize > 0) && (CertListSize >= CertList->SignatureListSize)) {\r
+    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
+      CertData  = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+      CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+\r
+      for (Index = 0; Index < CertCount; Index++) {\r
+        //\r
+        // Iterate each Signature Data Node within this CertList for verify.\r
+        //\r
+        RootCert     = CertData->SignatureData;\r
+        RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
+\r
+        //\r
+        // Call AuthenticodeVerify library to Verify Authenticode struct.\r
+        //\r
+        IsForbidden = AuthenticodeVerify (\r
+                        AuthData,\r
+                        AuthDataSize,\r
+                        RootCert,\r
+                        RootCertSize,\r
+                        mImageDigest,\r
+                        mImageDigestSize\r
+                        );\r
+        if (IsForbidden) {\r
+          SecureBootHook (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
+          goto Done;\r
+        }\r
+\r
+        CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);\r
+      }\r
+    }\r
+\r
+    CertListSize -= CertList->SignatureListSize;\r
+    CertList      = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+  }\r
+\r
+  //\r
+  // Check X.509 Certificate Hash & Possible Timestamp.\r
+  //\r
+\r
   //\r
   // Retrieve the certificate stack from AuthData\r
   // The output CertStack format will be:\r
@@ -1254,26 +1323,19 @@ IsForbiddenByDbx (
   //       UINT8  Certn[];\r
   //\r
   Pkcs7GetSigners (AuthData, AuthDataSize, &CertBuffer, &BufferLength, &TrustedCert, &TrustedCertLength);\r
-  if (BufferLength == 0) {\r
+  if ((BufferLength == 0) || (CertBuffer == NULL)) {\r
     IsForbidden = TRUE;\r
     goto Done;\r
   }\r
 \r
   //\r
-  // Check if any certificates in AuthData is in the forbidden database.\r
+  // Check if any hash of certificates embedded in AuthData is in the forbidden database.\r
   //\r
   CertNumber = (UINT8) (*CertBuffer);\r
   CertPtr    = CertBuffer + 1;\r
   for (Index = 0; Index < CertNumber; Index++) {\r
     CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr);\r
     Cert     = (UINT8 *)CertPtr + sizeof (UINT32);\r
-    if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, Cert, &gEfiCertX509Guid, CertSize)) {\r
-      //\r
-      // Raw certificate in dbx means the image signed by the certificate is forbidden.\r
-      //\r
-      IsForbidden = TRUE;\r
-      goto Done;\r
-    }\r
 \r
     if (IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime)) {\r
       //\r
@@ -1326,11 +1388,15 @@ IsAllowedByDb (
   UINTN                     RootCertSize;\r
   UINTN                     Index;\r
   UINTN                     CertCount;\r
+  UINTN                     DbxDataSize;\r
+  UINT8                     *DbxData;\r
+  EFI_TIME                  RevocationTime;\r
 \r
   Data         = NULL;\r
   CertList     = NULL;\r
   Cert         = NULL;\r
   RootCert     = NULL;\r
+  DbxData      = NULL;\r
   RootCertSize = 0;\r
   VerifyStatus = FALSE;\r
 \r
@@ -1375,7 +1441,30 @@ IsAllowedByDb (
                            mImageDigestSize\r
                            );\r
           if (VerifyStatus) {\r
-            SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
+            //\r
+            // Here We still need to check if this RootCert's Hash is revoked\r
+            //\r
+            Status   = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL);\r
+            if (Status == EFI_BUFFER_TOO_SMALL) {\r
+              goto Done;\r
+            }\r
+            DbxData = (UINT8 *) AllocateZeroPool (DataSize);\r
+            if (DbxData == NULL) {\r
+              goto Done;\r
+            }\r
+\r
+            Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData);\r
+            if (EFI_ERROR (Status)) {\r
+              goto Done;\r
+            }\r
+\r
+            if (IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime)) {\r
+              //\r
+              // Check the timestamp signature and signing time to determine if the image can be trusted.\r
+              //\r
+              VerifyStatus = PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime);\r
+            }\r
+\r
             goto Done;\r
           }\r
 \r
@@ -1389,9 +1478,16 @@ IsAllowedByDb (
   }\r
 \r
 Done:\r
+  if (VerifyStatus) {\r
+    SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
+  }\r
+\r
   if (Data != NULL) {\r
     FreePool (Data);\r
   }\r
+  if (DbxData != NULL) {\r
+    FreePool (DbxData);\r
+  }\r
 \r
   return VerifyStatus;\r
 }\r
@@ -1472,6 +1568,7 @@ DxeImageVerificationHandler (
   UINTN                                AuthDataSize;\r
   EFI_IMAGE_DATA_DIRECTORY             *SecDataDir;\r
   UINT32                               OffSet;\r
+  CHAR16                               *NameStr;\r
 \r
   SignatureList     = NULL;\r
   SignatureListSize = 0;\r
@@ -1662,7 +1759,7 @@ DxeImageVerificationHandler (
   //\r
   for (OffSet = SecDataDir->VirtualAddress;\r
        OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);\r
-       OffSet += WinCertificate->dwLength, OffSet += ALIGN_SIZE (OffSet)) {\r
+       OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength))) {\r
     WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);\r
     if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||\r
         (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {\r
@@ -1775,7 +1872,12 @@ Done:
     //\r
     // 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
+    NameStr = ConvertDevicePathToText (File, FALSE, TRUE);\r
+    AddImageExeInfo (Action, NameStr, File, SignatureList, SignatureListSize);\r
+    if (NameStr != NULL) {\r
+      DEBUG((EFI_D_INFO, "The image doesn't pass verification: %s\n", NameStr));\r
+      FreePool(NameStr);\r
+    }\r
     Status = EFI_SECURITY_VIOLATION;\r
   }\r
 \r