Revision: 13672
          http://edk2.svn.sourceforge.net/edk2/?rev=13672&view=rev
Author:   sfu5
Date:     2012-08-23 07:55:35 +0000 (Thu, 23 Aug 2012)
Log Message:
-----------
Update the DxeImageVerificationLib to handle the signed image which CertType is 
set to EFI_CERT_TYPE_PKCS7_GUID.

Signed-off-by: Fu Siyuan <siyuan...@intel.com>
Reviewed-by: Ye Ting  <ting...@intel.com>
Reviewed-by: Dong Guo <guo.d...@intel.com>

Modified Paths:
--------------
    
trunk/edk2/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
    
trunk/edk2/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf

Modified: 
trunk/edk2/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
===================================================================
--- 
trunk/edk2/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
    2012-08-23 06:53:51 UTC (rev 13671)
+++ 
trunk/edk2/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
    2012-08-23 07:55:35 UTC (rev 13672)
@@ -31,7 +31,6 @@
 //
 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader;
 UINT32                              mPeCoffHeaderOffset;
-EFI_IMAGE_DATA_DIRECTORY            *mSecDataDir      = NULL;
 EFI_GUID                            mCertType;
 
 //
@@ -585,24 +584,21 @@
   PE/COFF image is external input, so this function will validate its data 
structure
   within this image buffer before use.
 
+  @param[in]  AuthData            Pointer to the Authenticode Signature 
retrieved from signed image.
+  @param[in]  AuthDataSize        Size of the Authenticode Signature in bytes.
+  
   @retval EFI_UNSUPPORTED             Hash algorithm is not supported.
   @retval EFI_SUCCESS                 Hash successfully.
 
 **/
 EFI_STATUS
 HashPeImageByType (
-  VOID
+  IN UINT8              *AuthData,
+  IN UINTN              AuthDataSize
   )
 {
   UINT8                     Index;
-  WIN_CERTIFICATE_EFI_PKCS  *PkcsCertData;
 
-  PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + 
mSecDataDir->VirtualAddress);
-
-  if (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32) {
-    return EFI_UNSUPPORTED;
-  }
-
   for (Index = 0; Index < HASHALG_MAX; Index++) {
     //
     // Check the Hash algorithm in PE/COFF Authenticode.
@@ -616,18 +612,18 @@
     //    This field has the fixed offset (+32) in final Authenticode ASN.1 
data.
     //    Fixed offset (+32) is calculated based on two bytes of length 
encoding.
     //
-    if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
+    if ((*(AuthData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) {
       //
       // Only support two bytes of Long Form of Length Encoding.
       //
       continue;
     }
 
-    if (PkcsCertData->Hdr.dwLength < sizeof (WIN_CERTIFICATE_EFI_PKCS) + 32 + 
mHash[Index].OidLength) {
+    if (AuthDataSize < 32 + mHash[Index].OidLength) {
       return EFI_UNSUPPORTED;
     }
 
-    if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, 
mHash[Index].OidLength) == 0) {
+    if (CompareMem (AuthData + 32, mHash[Index].OidValue, 
mHash[Index].OidLength) == 0) {
       break;
     }
   }
@@ -875,8 +871,10 @@
   Verify PKCS#7 SignedData using certificate found in Variable which formatted
   as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.
 
-  @param VariableName  Name of Variable to search for Certificate.
-  @param VendorGuid    Variable vendor GUID.
+  @param[in]  AuthData      Pointer to the Authenticode Signature retrieved 
from signed image.
+  @param[in]  AuthDataSize  Size of the Authenticode Signature in bytes.
+  @param[in]  VariableName  Name of Variable to search for Certificate.
+  @param[in]  VendorGuid    Variable vendor GUID.
 
   @retval TRUE         Image pass verification.
   @retval FALSE        Image fail verification.
@@ -884,13 +882,14 @@
 **/
 BOOLEAN
 IsPkcsSignedDataVerifiedBySignatureList (
+  IN UINT8              *AuthData,
+  IN UINTN              AuthDataSize,
   IN CHAR16             *VariableName,
   IN EFI_GUID           *VendorGuid
   )
 {
   EFI_STATUS                Status;
   BOOLEAN                   VerifyStatus;
-  WIN_CERTIFICATE_EFI_PKCS  *PkcsCertData;
   EFI_SIGNATURE_LIST        *CertList;
   EFI_SIGNATURE_DATA        *Cert;
   UINTN                     DataSize;
@@ -906,7 +905,6 @@
   RootCert     = NULL;
   RootCertSize = 0;
   VerifyStatus = FALSE;
-  PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + 
mSecDataDir->VirtualAddress);
 
   DataSize = 0;
   Status   = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, 
NULL);
@@ -940,8 +938,8 @@
           // Call AuthenticodeVerify library to Verify Authenticode struct.
           //
           VerifyStatus = AuthenticodeVerify (
-                           PkcsCertData->CertData,
-                           PkcsCertData->Hdr.dwLength - 
sizeof(PkcsCertData->Hdr),
+                           AuthData,
+                           AuthDataSize,
                            RootCert,
                            RootCertSize,
                            mImageDigest,
@@ -969,19 +967,23 @@
 /**
   Verify certificate in WIN_CERT_TYPE_PKCS_SIGNED_DATA format.
 
+  @param[in]  AuthData      Pointer to the Authenticode Signature retrieved 
from signed image.
+  @param[in]  AuthDataSize  Size of the Authenticode Signature in bytes.
+
   @retval EFI_SUCCESS                 Image pass verification.
   @retval EFI_SECURITY_VIOLATION      Image fail verification.
 
 **/
 EFI_STATUS
 VerifyCertPkcsSignedData (
-  VOID
+  IN UINT8              *AuthData,
+  IN UINTN              AuthDataSize
   )
 {
   //
   // 1: Find certificate from DBX forbidden database for revoked certificate.
   //
-  if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE1, 
&gEfiImageSecurityDatabaseGuid)) {
+  if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, 
EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {
     //
     // DBX is forbidden database, if Authenticode verification pass with
     // one of the certificate in DBX, this image should be rejected.
@@ -992,7 +994,7 @@
   //
   // 2: Find certificate from DB database and try to verify authenticode 
struct.
   //
-  if (IsPkcsSignedDataVerifiedBySignatureList (EFI_IMAGE_SECURITY_DATABASE, 
&gEfiImageSecurityDatabaseGuid)) {
+  if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, 
EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {
     return EFI_SUCCESS;
   } else {
     return EFI_SECURITY_VIOLATION;
@@ -1081,10 +1083,17 @@
   PE_COFF_LOADER_IMAGE_CONTEXT         ImageContext;
   UINT32                               NumberOfRvaAndSizes;
   UINT32                               CertSize;
+  WIN_CERTIFICATE_EFI_PKCS             *PkcsCertData;
+  WIN_CERTIFICATE_UEFI_GUID            *WinCertUefiGuid;
+  UINT8                                *AuthData;
+  UINTN                                AuthDataSize;
+  EFI_IMAGE_DATA_DIRECTORY             *SecDataDir;
 
   SignatureList     = NULL;
   SignatureListSize = 0;
   WinCertificate    = NULL;
+  SecDataDir        = NULL;
+  PkcsCertData      = NULL;
   Action            = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
   Status            = EFI_ACCESS_DENIED;
   //
@@ -1207,7 +1216,7 @@
     //
     NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;
     if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
-      mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) 
&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
+      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) 
&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
     }        
   } else {
     //
@@ -1215,11 +1224,11 @@
     //
     NumberOfRvaAndSizes = 
mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
     if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {
-      mSecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) 
&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
+      SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) 
&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
     }
   }
 
-  if ((mSecDataDir == NULL) || ((mSecDataDir != NULL) && (mSecDataDir->Size == 
0))) {
+  if ((SecDataDir == NULL) || ((SecDataDir != NULL) && (SecDataDir->Size == 
0))) {
     //
     // This image is not signed.
     //
@@ -1250,24 +1259,48 @@
   //
   // Verify signature of executables.
   //
-  WinCertificate = (WIN_CERTIFICATE *) (mImageBase + 
mSecDataDir->VirtualAddress);
+  WinCertificate = (WIN_CERTIFICATE *) (mImageBase + 
SecDataDir->VirtualAddress);
 
   CertSize = sizeof (WIN_CERTIFICATE);
 
-  if ((mSecDataDir->Size <= CertSize) || (mSecDataDir->Size < 
WinCertificate->dwLength)) {
+  if ((SecDataDir->Size <= CertSize) || (SecDataDir->Size < 
WinCertificate->dwLength)) {
     goto Done;
   }
 
+  //
+  // Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed 
data is supported.
+  //
   if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
     //
-    // Verify Pkcs signed data type.
+    // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is 
described in the 
+    // Authenticode specification.
     //
-    Status = HashPeImageByType();
+    PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;
+    AuthData   = PkcsCertData->CertData;
+    AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);
+    
+    Status = HashPeImageByType (AuthData, AuthDataSize);
     if (EFI_ERROR (Status)) {
       goto Done;
     }
+
+    VerifyStatus = VerifyCertPkcsSignedData (AuthData, AuthDataSize);
+  } else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
+    //
+    // The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is 
described in UEFI Spec.
+    //
+    WinCertUefiGuid = (WIN_CERTIFICATE_UEFI_GUID *) WinCertificate;
+    if (!CompareGuid(&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {
+      goto Done;
+    }
+    AuthData = WinCertUefiGuid->CertData;
+    AuthDataSize = WinCertUefiGuid->Hdr.dwLength - 
OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
     
-    VerifyStatus = VerifyCertPkcsSignedData ();
+    Status = HashPeImageByType (AuthData, AuthDataSize);
+    if (EFI_ERROR (Status)) {
+      goto Done;
+    }
+    VerifyStatus = VerifyCertPkcsSignedData (AuthData, AuthDataSize);
   } else {
     goto Done;
   }

Modified: 
trunk/edk2/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
===================================================================
--- 
trunk/edk2/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
  2012-08-23 06:53:51 UTC (rev 13671)
+++ 
trunk/edk2/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
  2012-08-23 07:55:35 UTC (rev 13672)
@@ -68,6 +68,7 @@
   gEfiCertSha256Guid
   gEfiCertX509Guid
   gEfiCertRsa2048Guid
+  gEfiCertPkcs7Guid
   
 [Pcd]
   gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
edk2-commits mailing list
edk2-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to