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