\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
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
)\r
{\r
PKCS7 *Pkcs7;\r
- BIO *CertBio;\r
BIO *DataBio;\r
BOOLEAN Status;\r
X509 *Cert;\r
}\r
\r
Pkcs7 = NULL;\r
- CertBio = NULL;\r
DataBio = NULL;\r
Cert = NULL;\r
CertStore = NULL;\r
//\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
//\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
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
// 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