]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Verify.c
CryptoPkg Updates to support RFC3161 timestamp signature verification.
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptPkcs7Verify.c
CommitLineData
532616bb 1/** @file\r
2 PKCS#7 SignedData Verification Wrapper Implementation over OpenSSL.\r
3\r
4 Caution: This module requires additional review when modified.\r
5 This library will have external input - signature (e.g. UEFI Authenticated\r
6 Variable). It may by input in SMM mode.\r
7 This external input must be validated carefully to avoid security issue like\r
8 buffer overflow, integer overflow.\r
9\r
10 WrapPkcs7Data(), Pkcs7GetSigners(), Pkcs7Verify() will get UEFI Authenticated\r
11 Variable and will do basic check for data structure.\r
12\r
2ac68e8b 13Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
532616bb 14This program and the accompanying materials\r
15are licensed and made available under the terms and conditions of the BSD License\r
16which accompanies this distribution. The full text of the license may be found at\r
17http://opensource.org/licenses/bsd-license.php\r
18\r
19THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
20WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
21\r
22**/\r
23\r
24#include "InternalCryptLib.h"\r
25\r
26#include <openssl/objects.h>\r
27#include <openssl/x509.h>\r
02ee8d3b 28#include <openssl/x509v3.h>\r
532616bb 29#include <openssl/pkcs7.h>\r
30\r
31UINT8 mOidValue[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 };\r
32\r
33/**\r
34 Verification callback function to override any existing callbacks in OpenSSL\r
35 for intermediate certificate supports.\r
36\r
37 @param[in] Status Original status before calling this callback.\r
38 @param[in] Context X509 store context.\r
39\r
40 @retval 1 Current X509 certificate is verified successfully.\r
41 @retval 0 Verification failed.\r
42\r
43**/\r
44int\r
45X509VerifyCb (\r
46 IN int Status,\r
47 IN X509_STORE_CTX *Context\r
48 )\r
49{\r
50 X509_OBJECT *Obj;\r
51 INTN Error;\r
52 INTN Index;\r
53 INTN Count;\r
54\r
55 Obj = NULL;\r
56 Error = (INTN) X509_STORE_CTX_get_error (Context);\r
57\r
58 //\r
59 // X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT and X509_V_ERR_UNABLE_TO_GET_ISSUER_\r
60 // CERT_LOCALLY mean a X509 certificate is not self signed and its issuer\r
61 // can not be found in X509_verify_cert of X509_vfy.c.\r
62 // In order to support intermediate certificate node, we override the\r
63 // errors if the certification is obtained from X509 store, i.e. it is\r
64 // a trusted ceritifcate node that is enrolled by user.\r
65 // Besides,X509_V_ERR_CERT_UNTRUSTED and X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE\r
66 // are also ignored to enable such feature.\r
67 //\r
68 if ((Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) ||\r
69 (Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)) {\r
70 Obj = (X509_OBJECT *) malloc (sizeof (X509_OBJECT));\r
71 if (Obj == NULL) {\r
72 return 0;\r
73 }\r
74\r
75 Obj->type = X509_LU_X509;\r
76 Obj->data.x509 = Context->current_cert;\r
77\r
78 CRYPTO_w_lock (CRYPTO_LOCK_X509_STORE);\r
79\r
80 if (X509_OBJECT_retrieve_match (Context->ctx->objs, Obj)) {\r
81 Status = 1;\r
82 } else {\r
83 //\r
84 // If any certificate in the chain is enrolled as trusted certificate,\r
85 // pass the certificate verification.\r
86 //\r
87 if (Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {\r
88 Count = (INTN) sk_X509_num (Context->chain);\r
89 for (Index = 0; Index < Count; Index++) {\r
90 Obj->data.x509 = sk_X509_value (Context->chain, (int) Index);\r
91 if (X509_OBJECT_retrieve_match (Context->ctx->objs, Obj)) {\r
92 Status = 1;\r
93 break;\r
94 }\r
95 }\r
96 }\r
97 }\r
98\r
99 CRYPTO_w_unlock (CRYPTO_LOCK_X509_STORE);\r
100 }\r
101\r
102 if ((Error == X509_V_ERR_CERT_UNTRUSTED) ||\r
103 (Error == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE)) {\r
104 Status = 1;\r
105 }\r
106\r
107 if (Obj != NULL) {\r
108 OPENSSL_free (Obj);\r
109 }\r
110\r
111 return Status;\r
112}\r
113\r
114/**\r
115 Check input P7Data is a wrapped ContentInfo structure or not. If not construct\r
116 a new structure to wrap P7Data.\r
117\r
118 Caution: This function may receive untrusted input.\r
119 UEFI Authenticated Variable is external input, so this function will do basic\r
120 check for PKCS#7 data structure.\r
121\r
122 @param[in] P7Data Pointer to the PKCS#7 message to verify.\r
123 @param[in] P7Length Length of the PKCS#7 message in bytes.\r
124 @param[out] WrapFlag If TRUE P7Data is a ContentInfo structure, otherwise\r
125 return FALSE.\r
2ac68e8b 126 @param[out] WrapData If return status of this function is TRUE:\r
532616bb 127 1) when WrapFlag is TRUE, pointer to P7Data.\r
128 2) when WrapFlag is FALSE, pointer to a new ContentInfo\r
129 structure. It's caller's responsibility to free this\r
130 buffer.\r
131 @param[out] WrapDataSize Length of ContentInfo structure in bytes.\r
132\r
133 @retval TRUE The operation is finished successfully.\r
134 @retval FALSE The operation is failed due to lack of resources.\r
135\r
136**/\r
137BOOLEAN\r
138WrapPkcs7Data (\r
139 IN CONST UINT8 *P7Data,\r
140 IN UINTN P7Length,\r
141 OUT BOOLEAN *WrapFlag,\r
142 OUT UINT8 **WrapData,\r
143 OUT UINTN *WrapDataSize\r
144 )\r
145{\r
146 BOOLEAN Wrapped;\r
147 UINT8 *SignedData;\r
148\r
149 //\r
150 // Check whether input P7Data is a wrapped ContentInfo structure or not.\r
151 //\r
152 Wrapped = FALSE;\r
153 if ((P7Data[4] == 0x06) && (P7Data[5] == 0x09)) {\r
154 if (CompareMem (P7Data + 6, mOidValue, sizeof (mOidValue)) == 0) {\r
155 if ((P7Data[15] == 0xA0) && (P7Data[16] == 0x82)) {\r
156 Wrapped = TRUE;\r
157 }\r
158 }\r
159 }\r
160\r
161 if (Wrapped) {\r
162 *WrapData = (UINT8 *) P7Data;\r
163 *WrapDataSize = P7Length;\r
164 } else {\r
165 //\r
166 // Wrap PKCS#7 signeddata to a ContentInfo structure - add a header in 19 bytes.\r
167 //\r
168 *WrapDataSize = P7Length + 19;\r
169 *WrapData = malloc (*WrapDataSize);\r
170 if (*WrapData == NULL) {\r
171 *WrapFlag = Wrapped;\r
172 return FALSE;\r
173 }\r
174\r
175 SignedData = *WrapData;\r
176\r
177 //\r
178 // Part1: 0x30, 0x82.\r
179 //\r
180 SignedData[0] = 0x30;\r
181 SignedData[1] = 0x82;\r
182\r
183 //\r
184 // Part2: Length1 = P7Length + 19 - 4, in big endian.\r
185 //\r
186 SignedData[2] = (UINT8) (((UINT16) (*WrapDataSize - 4)) >> 8);\r
187 SignedData[3] = (UINT8) (((UINT16) (*WrapDataSize - 4)) & 0xff);\r
188\r
189 //\r
190 // Part3: 0x06, 0x09.\r
191 //\r
192 SignedData[4] = 0x06;\r
193 SignedData[5] = 0x09;\r
194\r
195 //\r
196 // Part4: OID value -- 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x07 0x02.\r
197 //\r
198 CopyMem (SignedData + 6, mOidValue, sizeof (mOidValue));\r
199\r
200 //\r
201 // Part5: 0xA0, 0x82.\r
202 //\r
203 SignedData[15] = 0xA0;\r
204 SignedData[16] = 0x82;\r
205\r
206 //\r
207 // Part6: Length2 = P7Length, in big endian.\r
208 //\r
209 SignedData[17] = (UINT8) (((UINT16) P7Length) >> 8);\r
210 SignedData[18] = (UINT8) (((UINT16) P7Length) & 0xff);\r
211\r
212 //\r
213 // Part7: P7Data.\r
214 //\r
215 CopyMem (SignedData + 19, P7Data, P7Length);\r
216 }\r
217\r
218 *WrapFlag = Wrapped;\r
219 return TRUE;\r
220}\r
221\r
efad60c5 222/**\r
223 Pop single certificate from STACK_OF(X509).\r
224\r
225 If X509Stack, Cert, or CertSize is NULL, then return FALSE.\r
226\r
227 @param[in] X509Stack Pointer to a X509 stack object.\r
228 @param[out] Cert Pointer to a X509 certificate.\r
229 @param[out] CertSize Length of output X509 certificate in bytes.\r
2ac68e8b 230\r
efad60c5 231 @retval TRUE The X509 stack pop succeeded.\r
232 @retval FALSE The pop operation failed.\r
233\r
234**/\r
235BOOLEAN\r
236X509PopCertificate (\r
237 IN VOID *X509Stack,\r
238 OUT UINT8 **Cert,\r
239 OUT UINTN *CertSize\r
240 )\r
241{\r
242 BIO *CertBio;\r
243 X509 *X509Cert;\r
244 STACK_OF(X509) *CertStack;\r
245 BOOLEAN Status;\r
eb58f559 246 INT32 Result;\r
247 INT32 Length;\r
efad60c5 248 VOID *Buffer;\r
249\r
250 Status = FALSE;\r
251\r
252 if ((X509Stack == NULL) || (Cert == NULL) || (CertSize == NULL)) {\r
253 return Status;\r
254 }\r
255\r
256 CertStack = (STACK_OF(X509) *) X509Stack;\r
257\r
258 X509Cert = sk_X509_pop (CertStack);\r
259\r
260 if (X509Cert == NULL) {\r
261 return Status;\r
262 }\r
263\r
264 Buffer = NULL;\r
265\r
266 CertBio = BIO_new (BIO_s_mem ());\r
267 if (CertBio == NULL) {\r
268 return Status;\r
269 }\r
270\r
271 Result = i2d_X509_bio (CertBio, X509Cert);\r
272 if (Result == 0) {\r
273 goto _Exit;\r
274 }\r
275\r
276 Length = ((BUF_MEM *) CertBio->ptr)->length;\r
277 if (Length <= 0) {\r
278 goto _Exit;\r
279 }\r
280\r
281 Buffer = malloc (Length);\r
282 if (Buffer == NULL) {\r
283 goto _Exit;\r
284 }\r
285\r
286 Result = BIO_read (CertBio, Buffer, Length);\r
287 if (Result != Length) {\r
288 goto _Exit;\r
289 }\r
290\r
291 *Cert = Buffer;\r
292 *CertSize = Length;\r
293\r
294 Status = TRUE;\r
295\r
296_Exit:\r
297\r
298 BIO_free (CertBio);\r
299\r
300 if (!Status && (Buffer != NULL)) {\r
301 free (Buffer);\r
302 }\r
303\r
304 return Status;\r
305}\r
306\r
532616bb 307/**\r
308 Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7:\r
309 Cryptographic Message Syntax Standard". The input signed data could be wrapped\r
310 in a ContentInfo structure.\r
311\r
312 If P7Data, CertStack, StackLength, TrustedCert or CertLength is NULL, then\r
313 return FALSE. If P7Length overflow, then return FAlSE.\r
314\r
315 Caution: This function may receive untrusted input.\r
316 UEFI Authenticated Variable is external input, so this function will do basic\r
317 check for PKCS#7 data structure.\r
318\r
319 @param[in] P7Data Pointer to the PKCS#7 message to verify.\r
320 @param[in] P7Length Length of the PKCS#7 message in bytes.\r
321 @param[out] CertStack Pointer to Signer's certificates retrieved from P7Data.\r
322 It's caller's responsiblity to free the buffer.\r
323 @param[out] StackLength Length of signer's certificates in bytes.\r
324 @param[out] TrustedCert Pointer to a trusted certificate from Signer's certificates.\r
325 It's caller's responsiblity to free the buffer.\r
326 @param[out] CertLength Length of the trusted certificate in bytes.\r
327\r
328 @retval TRUE The operation is finished successfully.\r
329 @retval FALSE Error occurs during the operation.\r
330\r
331**/\r
332BOOLEAN\r
333EFIAPI\r
334Pkcs7GetSigners (\r
335 IN CONST UINT8 *P7Data,\r
336 IN UINTN P7Length,\r
337 OUT UINT8 **CertStack,\r
338 OUT UINTN *StackLength,\r
339 OUT UINT8 **TrustedCert,\r
340 OUT UINTN *CertLength\r
341 )\r
342{\r
343 PKCS7 *Pkcs7;\r
344 BOOLEAN Status;\r
345 UINT8 *SignedData;\r
346 UINT8 *Temp;\r
347 UINTN SignedDataSize;\r
348 BOOLEAN Wrapped;\r
349 STACK_OF(X509) *Stack;\r
350 UINT8 Index;\r
351 UINT8 *CertBuf;\r
352 UINT8 *OldBuf;\r
353 UINTN BufferSize;\r
354 UINTN OldSize;\r
355 UINT8 *SingleCert;\r
356 UINTN SingleCertSize;\r
357\r
358 if ((P7Data == NULL) || (CertStack == NULL) || (StackLength == NULL) ||\r
359 (TrustedCert == NULL) || (CertLength == NULL) || (P7Length > INT_MAX)) {\r
360 return FALSE;\r
361 }\r
2ac68e8b 362\r
532616bb 363 Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize);\r
364 if (!Status) {\r
365 return Status;\r
366 }\r
367\r
368 Status = FALSE;\r
369 Pkcs7 = NULL;\r
370 Stack = NULL;\r
371 CertBuf = NULL;\r
372 OldBuf = NULL;\r
373 SingleCert = NULL;\r
374\r
375 //\r
376 // Retrieve PKCS#7 Data (DER encoding)\r
377 //\r
378 if (SignedDataSize > INT_MAX) {\r
379 goto _Exit;\r
380 }\r
381\r
382 Temp = SignedData;\r
383 Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &Temp, (int) SignedDataSize);\r
384 if (Pkcs7 == NULL) {\r
385 goto _Exit;\r
386 }\r
387\r
388 //\r
389 // Check if it's PKCS#7 Signed Data (for Authenticode Scenario)\r
390 //\r
391 if (!PKCS7_type_is_signed (Pkcs7)) {\r
392 goto _Exit;\r
393 }\r
394\r
395 Stack = PKCS7_get0_signers(Pkcs7, NULL, PKCS7_BINARY);\r
396 if (Stack == NULL) {\r
397 goto _Exit;\r
398 }\r
399\r
400 //\r
401 // Convert CertStack to buffer in following format:\r
402 // UINT8 CertNumber;\r
403 // UINT32 Cert1Length;\r
404 // UINT8 Cert1[];\r
405 // UINT32 Cert2Length;\r
406 // UINT8 Cert2[];\r
407 // ...\r
408 // UINT32 CertnLength;\r
409 // UINT8 Certn[];\r
410 //\r
411 BufferSize = sizeof (UINT8);\r
412 OldSize = BufferSize;\r
2ac68e8b 413\r
532616bb 414 for (Index = 0; ; Index++) {\r
415 Status = X509PopCertificate (Stack, &SingleCert, &SingleCertSize);\r
416 if (!Status) {\r
417 break;\r
418 }\r
419\r
420 OldSize = BufferSize;\r
421 OldBuf = CertBuf;\r
422 BufferSize = OldSize + SingleCertSize + sizeof (UINT32);\r
423 CertBuf = malloc (BufferSize);\r
424\r
425 if (CertBuf == NULL) {\r
426 goto _Exit;\r
427 }\r
428\r
429 if (OldBuf != NULL) {\r
430 CopyMem (CertBuf, OldBuf, OldSize);\r
431 free (OldBuf);\r
432 OldBuf = NULL;\r
433 }\r
434\r
435 WriteUnaligned32 ((UINT32 *) (CertBuf + OldSize), (UINT32) SingleCertSize);\r
436 CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, SingleCertSize);\r
437\r
438 free (SingleCert);\r
439 SingleCert = NULL;\r
440 }\r
441\r
442 if (CertBuf != NULL) {\r
443 //\r
444 // Update CertNumber.\r
445 //\r
446 CertBuf[0] = Index;\r
447\r
448 *CertLength = BufferSize - OldSize - sizeof (UINT32);\r
449 *TrustedCert = malloc (*CertLength);\r
450 if (*TrustedCert == NULL) {\r
451 goto _Exit;\r
452 }\r
453\r
454 CopyMem (*TrustedCert, CertBuf + OldSize + sizeof (UINT32), *CertLength);\r
455 *CertStack = CertBuf;\r
456 *StackLength = BufferSize;\r
457 Status = TRUE;\r
2ac68e8b 458 }\r
532616bb 459\r
460_Exit:\r
461 //\r
462 // Release Resources\r
463 //\r
464 if (!Wrapped) {\r
465 free (SignedData);\r
466 }\r
467\r
468 if (Pkcs7 != NULL) {\r
469 PKCS7_free (Pkcs7);\r
470 }\r
471\r
472 if (Stack != NULL) {\r
473 sk_X509_pop_free(Stack, X509_free);\r
474 }\r
475\r
476 if (SingleCert != NULL) {\r
477 free (SingleCert);\r
478 }\r
479\r
480 if (!Status && (CertBuf != NULL)) {\r
481 free (CertBuf);\r
482 *CertStack = NULL;\r
483 }\r
484\r
485 if (OldBuf != NULL) {\r
486 free (OldBuf);\r
487 }\r
2ac68e8b 488\r
532616bb 489 return Status;\r
490}\r
491\r
492/**\r
493 Wrap function to use free() to free allocated memory for certificates.\r
494\r
495 @param[in] Certs Pointer to the certificates to be freed.\r
496\r
497**/\r
498VOID\r
499EFIAPI\r
500Pkcs7FreeSigners (\r
501 IN UINT8 *Certs\r
502 )\r
503{\r
504 if (Certs == NULL) {\r
505 return;\r
506 }\r
507\r
508 free (Certs);\r
509}\r
510\r
511/**\r
512 Verifies the validility of a PKCS#7 signed data as described in "PKCS #7:\r
513 Cryptographic Message Syntax Standard". The input signed data could be wrapped\r
514 in a ContentInfo structure.\r
515\r
516 If P7Data, TrustedCert or InData is NULL, then return FALSE.\r
517 If P7Length, CertLength or DataLength overflow, then return FAlSE.\r
518\r
519 Caution: This function may receive untrusted input.\r
520 UEFI Authenticated Variable is external input, so this function will do basic\r
521 check for PKCS#7 data structure.\r
522\r
523 @param[in] P7Data Pointer to the PKCS#7 message to verify.\r
524 @param[in] P7Length Length of the PKCS#7 message in bytes.\r
525 @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which\r
526 is used for certificate chain verification.\r
527 @param[in] CertLength Length of the trusted certificate in bytes.\r
528 @param[in] InData Pointer to the content to be verified.\r
529 @param[in] DataLength Length of InData in bytes.\r
530\r
531 @retval TRUE The specified PKCS#7 signed data is valid.\r
532 @retval FALSE Invalid PKCS#7 signed data.\r
533\r
534**/\r
535BOOLEAN\r
536EFIAPI\r
537Pkcs7Verify (\r
538 IN CONST UINT8 *P7Data,\r
539 IN UINTN P7Length,\r
540 IN CONST UINT8 *TrustedCert,\r
541 IN UINTN CertLength,\r
542 IN CONST UINT8 *InData,\r
543 IN UINTN DataLength\r
544 )\r
545{\r
546 PKCS7 *Pkcs7;\r
532616bb 547 BIO *DataBio;\r
548 BOOLEAN Status;\r
549 X509 *Cert;\r
550 X509_STORE *CertStore;\r
551 UINT8 *SignedData;\r
552 UINT8 *Temp;\r
553 UINTN SignedDataSize;\r
554 BOOLEAN Wrapped;\r
555\r
556 //\r
557 // Check input parameters.\r
558 //\r
2ac68e8b 559 if (P7Data == NULL || TrustedCert == NULL || InData == NULL ||\r
532616bb 560 P7Length > INT_MAX || CertLength > INT_MAX || DataLength > INT_MAX) {\r
561 return FALSE;\r
562 }\r
2ac68e8b 563\r
532616bb 564 Pkcs7 = NULL;\r
532616bb 565 DataBio = NULL;\r
566 Cert = NULL;\r
567 CertStore = NULL;\r
568\r
569 //\r
570 // Register & Initialize necessary digest algorithms for PKCS#7 Handling\r
571 //\r
dda39f3a 572 if (EVP_add_digest (EVP_md5 ()) == 0) {\r
573 return FALSE;\r
574 }\r
575 if (EVP_add_digest (EVP_sha1 ()) == 0) {\r
576 return FALSE;\r
577 }\r
578 if (EVP_add_digest (EVP_sha256 ()) == 0) {\r
579 return FALSE;\r
580 }\r
2ac68e8b
QL
581 if (EVP_add_digest (EVP_sha384 ()) == 0) {\r
582 return FALSE;\r
583 }\r
584 if (EVP_add_digest (EVP_sha512 ()) == 0) {\r
585 return FALSE;\r
586 }\r
dda39f3a 587 if (EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA) == 0) {\r
588 return FALSE;\r
589 }\r
590\r
532616bb 591 Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize);\r
592 if (!Status) {\r
593 return Status;\r
594 }\r
595\r
596 Status = FALSE;\r
2ac68e8b 597\r
532616bb 598 //\r
599 // Retrieve PKCS#7 Data (DER encoding)\r
600 //\r
601 if (SignedDataSize > INT_MAX) {\r
602 goto _Exit;\r
603 }\r
604\r
605 Temp = SignedData;\r
606 Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &Temp, (int) SignedDataSize);\r
607 if (Pkcs7 == NULL) {\r
608 goto _Exit;\r
609 }\r
610\r
611 //\r
612 // Check if it's PKCS#7 Signed Data (for Authenticode Scenario)\r
613 //\r
614 if (!PKCS7_type_is_signed (Pkcs7)) {\r
615 goto _Exit;\r
616 }\r
617\r
618 //\r
619 // Read DER-encoded root certificate and Construct X509 Certificate\r
620 //\r
02ee8d3b 621 Cert = d2i_X509 (NULL, &TrustedCert, (long) CertLength);\r
532616bb 622 if (Cert == NULL) {\r
623 goto _Exit;\r
624 }\r
625\r
626 //\r
627 // Setup X509 Store for trusted certificate\r
628 //\r
629 CertStore = X509_STORE_new ();\r
630 if (CertStore == NULL) {\r
631 goto _Exit;\r
632 }\r
633 if (!(X509_STORE_add_cert (CertStore, Cert))) {\r
634 goto _Exit;\r
635 }\r
636\r
637 //\r
638 // Register customized X509 verification callback function to support\r
639 // trusted intermediate certificate anchor.\r
640 //\r
641 CertStore->verify_cb = X509VerifyCb;\r
642\r
643 //\r
644 // For generic PKCS#7 handling, InData may be NULL if the content is present\r
645 // in PKCS#7 structure. So ignore NULL checking here.\r
646 //\r
647 DataBio = BIO_new (BIO_s_mem ());\r
5b2956ea
YT
648 if (DataBio == NULL) {\r
649 goto _Exit;\r
650 }\r
651\r
652 if (BIO_write (DataBio, InData, (int) DataLength) <= 0) {\r
653 goto _Exit;\r
654 }\r
532616bb 655\r
02ee8d3b 656 //\r
657 // OpenSSL PKCS7 Verification by default checks for SMIME (email signing) and\r
658 // doesn't support the extended key usage for Authenticode Code Signing.\r
659 // Bypass the certificate purpose checking by enabling any purposes setting.\r
660 //\r
661 X509_STORE_set_purpose (CertStore, X509_PURPOSE_ANY);\r
662\r
532616bb 663 //\r
664 // Verifies the PKCS#7 signedData structure\r
665 //\r
666 Status = (BOOLEAN) PKCS7_verify (Pkcs7, NULL, CertStore, DataBio, NULL, PKCS7_BINARY);\r
667\r
668_Exit:\r
669 //\r
670 // Release Resources\r
671 //\r
672 BIO_free (DataBio);\r
532616bb 673 X509_free (Cert);\r
674 X509_STORE_free (CertStore);\r
675 PKCS7_free (Pkcs7);\r
676\r
677 if (!Wrapped) {\r
678 OPENSSL_free (SignedData);\r
679 }\r
680\r
681 return Status;\r
2ac68e8b 682}