]> git.proxmox.com Git - mirror_edk2.git/blobdiff - CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Verify.c
1. Enable the whole X509v3 extension checking.
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptPkcs7Verify.c
index 24f4c031d58e8c5df40864ca370941d8900f6f8b..471fbbbe25e07f5f6a6112a13a227a002f3172d2 100644 (file)
@@ -25,6 +25,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include <openssl/objects.h>\r
 #include <openssl/x509.h>\r
+#include <openssl/x509v3.h>\r
 #include <openssl/pkcs7.h>\r
 \r
 UINT8 mOidValue[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 };\r
@@ -218,6 +219,91 @@ WrapPkcs7Data (
   return TRUE;\r
 }\r
 \r
+/**\r
+  Pop single certificate from STACK_OF(X509).\r
+\r
+  If X509Stack, Cert, or CertSize is NULL, then return FALSE.\r
+\r
+  @param[in]  X509Stack       Pointer to a X509 stack object.\r
+  @param[out] Cert            Pointer to a X509 certificate.\r
+  @param[out] CertSize        Length of output X509 certificate in bytes.\r
+                                 \r
+  @retval     TRUE            The X509 stack pop succeeded.\r
+  @retval     FALSE           The pop operation failed.\r
+\r
+**/\r
+BOOLEAN\r
+X509PopCertificate (\r
+  IN  VOID  *X509Stack,\r
+  OUT UINT8 **Cert,\r
+  OUT UINTN *CertSize\r
+  )\r
+{\r
+  BIO             *CertBio;\r
+  X509            *X509Cert;\r
+  STACK_OF(X509)  *CertStack;\r
+  BOOLEAN         Status;\r
+  INT32           Result;\r
+  INT32           Length;\r
+  VOID            *Buffer;\r
+\r
+  Status = FALSE;\r
+\r
+  if ((X509Stack == NULL) || (Cert == NULL) || (CertSize == NULL)) {\r
+    return Status;\r
+  }\r
+\r
+  CertStack = (STACK_OF(X509) *) X509Stack;\r
+\r
+  X509Cert = sk_X509_pop (CertStack);\r
+\r
+  if (X509Cert == NULL) {\r
+    return Status;\r
+  }\r
+\r
+  Buffer = NULL;\r
+\r
+  CertBio = BIO_new (BIO_s_mem ());\r
+  if (CertBio == NULL) {\r
+    return Status;\r
+  }\r
+\r
+  Result = i2d_X509_bio (CertBio, X509Cert);\r
+  if (Result == 0) {\r
+    goto _Exit;\r
+  }\r
+\r
+  Length = ((BUF_MEM *) CertBio->ptr)->length;\r
+  if (Length <= 0) {\r
+    goto _Exit;\r
+  }\r
+\r
+  Buffer = malloc (Length);\r
+  if (Buffer == NULL) {\r
+    goto _Exit;\r
+  }\r
+\r
+  Result = BIO_read (CertBio, Buffer, Length);\r
+  if (Result != Length) {\r
+    goto _Exit;\r
+  }\r
+\r
+  *Cert     = Buffer;\r
+  *CertSize = Length;\r
+\r
+  Status = TRUE;\r
+\r
+_Exit:\r
+\r
+  BIO_free (CertBio);\r
+\r
+  if (!Status && (Buffer != NULL)) {\r
+    free (Buffer);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7:\r
   Cryptographic Message Syntax Standard". The input signed data could be wrapped\r
@@ -458,7 +544,6 @@ Pkcs7Verify (
   )\r
 {\r
   PKCS7       *Pkcs7;\r
-  BIO         *CertBio;\r
   BIO         *DataBio;\r
   BOOLEAN     Status;\r
   X509        *Cert;\r
@@ -477,7 +562,6 @@ Pkcs7Verify (
   }\r
   \r
   Pkcs7     = NULL;\r
-  CertBio   = NULL;\r
   DataBio   = NULL;\r
   Cert      = NULL;\r
   CertStore = NULL;\r
@@ -485,10 +569,19 @@ Pkcs7Verify (
   //\r
   // Register & Initialize necessary digest algorithms for PKCS#7 Handling\r
   //\r
-  EVP_add_digest (EVP_md5());\r
-  EVP_add_digest (EVP_sha1());\r
-  EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA);\r
-  EVP_add_digest (EVP_sha256());\r
+  if (EVP_add_digest (EVP_md5 ()) == 0) {\r
+    return FALSE;\r
+  }\r
+  if (EVP_add_digest (EVP_sha1 ()) == 0) {\r
+    return FALSE;\r
+  }\r
+  if (EVP_add_digest (EVP_sha256 ()) == 0) {\r
+    return FALSE;\r
+  }\r
+  if (EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA) == 0) {\r
+    return FALSE;\r
+  }\r
+\r
 \r
   Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize);\r
   if (!Status) {\r
@@ -520,12 +613,7 @@ Pkcs7Verify (
   //\r
   // Read DER-encoded root certificate and Construct X509 Certificate\r
   //\r
-  CertBio = BIO_new (BIO_s_mem ());\r
-  BIO_write (CertBio, TrustedCert, (int)CertLength);\r
-  if (CertBio == NULL) {\r
-    goto _Exit;\r
-  }\r
-  Cert = d2i_X509_bio (CertBio, NULL);\r
+  Cert = d2i_X509 (NULL, &TrustedCert, (long) CertLength);\r
   if (Cert == NULL) {\r
     goto _Exit;\r
   }\r
@@ -554,6 +642,13 @@ Pkcs7Verify (
   DataBio = BIO_new (BIO_s_mem ());\r
   BIO_write (DataBio, InData, (int)DataLength);\r
 \r
+  //\r
+  // OpenSSL PKCS7 Verification by default checks for SMIME (email signing) and\r
+  // doesn't support the extended key usage for Authenticode Code Signing.\r
+  // Bypass the certificate purpose checking by enabling any purposes setting.\r
+  //\r
+  X509_STORE_set_purpose (CertStore, X509_PURPOSE_ANY);\r
+\r
   //\r
   // Verifies the PKCS#7 signedData structure\r
   //\r
@@ -564,7 +659,6 @@ _Exit:
   // Release Resources\r
   //\r
   BIO_free (DataBio);\r
-  BIO_free (CertBio);\r
   X509_free (Cert);\r
   X509_STORE_free (CertStore);\r
   PKCS7_free (Pkcs7);\r