]> git.proxmox.com Git - mirror_edk2.git/blobdiff - CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c
CryptoPkg: Apply uncrustify changes
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptAuthenticode.c
index 0370fd77a5de077d560fd4951e6436040bc87317..aa4a33364d9240fc2b245af4942e4577f209282e 100644 (file)
@@ -1,14 +1,16 @@
 /** @file\r
   Authenticode Portable Executable Signature Verification over OpenSSL.\r
 \r
-Copyright (c) 2011, 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
-http://opensource.org/licenses/bsd-license.php\r
+  Caution: This module requires additional review when modified.\r
+  This library will have external input - signature (e.g. PE/COFF Authenticode).\r
+  This external input must be validated carefully to avoid security issue like\r
+  buffer overflow, integer overflow.\r
 \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  AuthenticodeVerify() will get PE/COFF Authenticode and will do basic check for\r
+  data structure.\r
+\r
+Copyright (c) 2011 - 2020, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -18,13 +20,23 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <openssl/x509.h>\r
 #include <openssl/pkcs7.h>\r
 \r
+//\r
+// OID ASN.1 Value for SPC_INDIRECT_DATA_OBJID\r
+//\r
+UINT8  mSpcIndirectOidValue[] = {\r
+  0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04\r
+};\r
 \r
 /**\r
-  Verifies the validility of a PE/COFF Authenticode Signature as described in "Windows\r
+  Verifies the validity of a PE/COFF Authenticode Signature as described in "Windows\r
   Authenticode Portable Executable Signature Format".\r
 \r
-  If AuthData is NULL, then ASSERT().\r
-  If ImageHash is NULL, then ASSERT().\r
+  If AuthData is NULL, then return FALSE.\r
+  If ImageHash is NULL, then return FALSE.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  PE/COFF Authenticode is external input, so this function will do basic check for\r
+  Authenticode data structure.\r
 \r
   @param[in]  AuthData     Pointer to the Authenticode Signature retrieved from signed\r
                            PE/COFF image to be verified.\r
@@ -32,7 +44,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
   @param[in]  TrustedCert  Pointer to a trusted/root certificate encoded in DER, which\r
                            is used for certificate chain verification.\r
   @param[in]  CertSize     Size of the trusted certificate in bytes.\r
-  @param[in]  ImageHash    Pointer to the original image file hash value. The procudure\r
+  @param[in]  ImageHash    Pointer to the original image file hash value. The procedure\r
                            for calculating the image hash value is described in Authenticode\r
                            specification.\r
   @param[in]  HashSize     Size of Image hash value in bytes.\r
@@ -54,18 +66,21 @@ AuthenticodeVerify (
 {\r
   BOOLEAN      Status;\r
   PKCS7        *Pkcs7;\r
+  CONST UINT8  *Temp;\r
   CONST UINT8  *OrigAuthData;\r
   UINT8        *SpcIndirectDataContent;\r
   UINT8        Asn1Byte;\r
   UINTN        ContentSize;\r
+  CONST UINT8  *SpcIndirectDataOid;\r
 \r
   //\r
-  // ASSERT if Authenticode Signature Data or PE Image Hash is NULL\r
+  // Check input parameters.\r
   //\r
-  ASSERT (AuthData  != NULL);\r
-  ASSERT (ImageHash != NULL);\r
+  if ((AuthData == NULL) || (TrustedCert == NULL) || (ImageHash == NULL)) {\r
+    return FALSE;\r
+  }\r
 \r
-  if (DataSize > INT_MAX) {\r
+  if ((DataSize > INT_MAX) || (CertSize > INT_MAX) || (HashSize > INT_MAX)) {\r
     return FALSE;\r
   }\r
 \r
@@ -76,7 +91,8 @@ AuthenticodeVerify (
   //\r
   // Retrieve & Parse PKCS#7 Data (DER encoding) from Authenticode Signature\r
   //\r
-  Pkcs7 = d2i_PKCS7 (NULL, &AuthData, (int)DataSize);\r
+  Temp  = AuthData;\r
+  Pkcs7 = d2i_PKCS7 (NULL, &Temp, (int)DataSize);\r
   if (Pkcs7 == NULL) {\r
     goto _Exit;\r
   }\r
@@ -84,7 +100,7 @@ AuthenticodeVerify (
   //\r
   // Check if it's PKCS#7 Signed Data (for Authenticode Scenario)\r
   //\r
-  if (!PKCS7_type_is_signed (Pkcs7)) {\r
+  if (!PKCS7_type_is_signed (Pkcs7) || PKCS7_get_detached (Pkcs7)) {\r
     goto _Exit;\r
   }\r
 \r
@@ -93,31 +109,57 @@ AuthenticodeVerify (
   //       some authenticode-specific structure. Use opaque ASN.1 string to retrieve\r
   //       PKCS#7 ContentInfo here.\r
   //\r
+  SpcIndirectDataOid = OBJ_get0_data (Pkcs7->d.sign->contents->type);\r
+  if ((OBJ_length (Pkcs7->d.sign->contents->type) != sizeof (mSpcIndirectOidValue)) ||\r
+      (CompareMem (\r
+         SpcIndirectDataOid,\r
+         mSpcIndirectOidValue,\r
+         sizeof (mSpcIndirectOidValue)\r
+         ) != 0))\r
+  {\r
+    //\r
+    // Un-matched SPC_INDIRECT_DATA_OBJID.\r
+    //\r
+    goto _Exit;\r
+  }\r
+\r
   SpcIndirectDataContent = (UINT8 *)(Pkcs7->d.sign->contents->d.other->value.asn1_string->data);\r
 \r
   //\r
   // Retrieve the SEQUENCE data size from ASN.1-encoded SpcIndirectDataContent.\r
   //\r
   Asn1Byte = *(SpcIndirectDataContent + 1);\r
+\r
   if ((Asn1Byte & 0x80) == 0) {\r
     //\r
-    // Short Form of Length Encoding\r
+    // Short Form of Length Encoding (Length < 128)\r
     //\r
-    ContentSize = (UINTN) (Asn1Byte & 0x7F);\r
+    ContentSize = (UINTN)(Asn1Byte & 0x7F);\r
     //\r
     // Skip the SEQUENCE Tag;\r
     //\r
     SpcIndirectDataContent += 2;\r
-  } else {\r
+  } else if ((Asn1Byte & 0x81) == 0x81) {\r
     //\r
-    // Long Form of Length Encoding (Assume Only two bytes here)\r
+    // Long Form of Length Encoding (128 <= Length < 255, Single Octet)\r
     //\r
-    ContentSize  = (UINTN) (*(SpcIndirectDataContent + 2));\r
-    ContentSize = (ContentSize << 8) + (UINTN)(*(SpcIndirectDataContent + 3));\r
+    ContentSize = (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 2));\r
+    //\r
+    // Skip the SEQUENCE Tag;\r
+    //\r
+    SpcIndirectDataContent += 3;\r
+  } else if ((Asn1Byte & 0x82) == 0x82) {\r
+    //\r
+    // Long Form of Length Encoding (Length > 255, Two Octet)\r
+    //\r
+    ContentSize = (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 2));\r
+    ContentSize = (ContentSize << 8) + (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 3));\r
     //\r
     // Skip the SEQUENCE Tag;\r
     //\r
     SpcIndirectDataContent += 4;\r
+  } else {\r
+    goto _Exit;\r
   }\r
 \r
   //\r
@@ -135,7 +177,7 @@ AuthenticodeVerify (
   //\r
   // Verifies the PKCS#7 Signed Data in PE/COFF Authenticode Signature\r
   //\r
-  Status = (BOOLEAN) Pkcs7Verify (OrigAuthData, DataSize, TrustedCert, CertSize, SpcIndirectDataContent, ContentSize);\r
+  Status = (BOOLEAN)Pkcs7Verify (OrigAuthData, DataSize, TrustedCert, CertSize, SpcIndirectDataContent, ContentSize);\r
 \r
 _Exit:\r
   //\r