2 PKCS#7 SignedData Verification Wrapper Implementation over OpenSSL.
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.
10 WrapPkcs7Data(), Pkcs7GetSigners(), Pkcs7Verify() will get UEFI Authenticated
11 Variable and will do basic check for data structure.
13 Copyright (c) 2009 - 2016, 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
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.
24 #include "InternalCryptLib.h"
26 #include <openssl/objects.h>
27 #include <openssl/x509.h>
28 #include <openssl/x509v3.h>
29 #include <openssl/pkcs7.h>
31 UINT8 mOidValue
[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 };
34 #if OPENSSL_VERSION_NUMBER < 0x10100000L
35 #define X509_OBJECT_get0_X509(obj) ((obj)->data.x509)
36 #define X509_OBJECT_get_type(obj) ((obj)->type)
37 #define X509_STORE_CTX_get0_cert(ctx) ((ctx)->cert)
38 #define X509_STORE_get0_objects(certs) ((certs)->objs)
39 #define X509_get_extended_key_usage(cert) ((cert)->ex_xkusage)
40 #if OPENSSL_VERSION_NUMBER < 0x10020000L
41 #define X509_STORE_CTX_get0_store(ctx) ((ctx)->ctx)
45 static int cert_in_store(X509
*cert
, X509_STORE_CTX
*ctx
)
48 obj
.type
= X509_LU_X509
;
50 return X509_OBJECT_retrieve_match(ctx
->ctx
->objs
, &obj
) != NULL
;
54 * Later versions of openssl will need this instead.
56 static int cert_in_store(X509
*cert
, X509_STORE_CTX
*ctx
)
58 STACK_OF(X509_OBJECT
) *objs
;
62 objs
= X509_STORE_get0_objects(X509_STORE_CTX_get0_store(ctx
));
64 for (i
= 0; i
< sk_X509_OBJECT_num(objs
); i
++) {
65 obj
= sk_X509_OBJECT_value(objs
, i
);
67 if (X509_OBJECT_get_type(obj
) == X509_LU_X509
&&
68 !X509_cmp(X509_OBJECT_get0_X509(obj
), cert
))
79 IN X509_STORE_CTX
*Context
84 Error
= (INTN
) X509_STORE_CTX_get_error (Context
);
86 /* Accept code-signing keys */
87 if (Error
== X509_V_ERR_INVALID_PURPOSE
&&
88 X509_get_extended_key_usage(X509_STORE_CTX_get0_cert(Context
)) == XKU_CODE_SIGN
) {
90 } else if (Error
== X509_V_ERR_CERT_UNTRUSTED
||
91 Error
== X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
||
92 Error
== X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
||
93 Error
== X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
) {
94 /* all certs in our cert database are explicitly trusted */
96 if (cert_in_store(X509_STORE_CTX_get_current_cert(Context
), Context
))
98 } else if (Error
== X509_V_ERR_CERT_HAS_EXPIRED
||
99 Error
== X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD
||
100 Error
== X509_V_ERR_CERT_NOT_YET_VALID
||
101 Error
== X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
||
102 Error
== X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD
) {
103 /* UEFI explicitly allows expired certificates */
106 } else if (Error
== X509_V_ERR_INVALID_CA
) {
107 /* Due to the historical reason, we have to relax the the x509 v3 extension
108 * check to allow the CA certificates without the CA flag in the basic
109 * constraints or KeyCertSign in the key usage to be loaded. In the future,
110 * this callback should be removed to enforce the proper check. */
119 Check input P7Data is a wrapped ContentInfo structure or not. If not construct
120 a new structure to wrap P7Data.
122 Caution: This function may receive untrusted input.
123 UEFI Authenticated Variable is external input, so this function will do basic
124 check for PKCS#7 data structure.
126 @param[in] P7Data Pointer to the PKCS#7 message to verify.
127 @param[in] P7Length Length of the PKCS#7 message in bytes.
128 @param[out] WrapFlag If TRUE P7Data is a ContentInfo structure, otherwise
130 @param[out] WrapData If return status of this function is TRUE:
131 1) when WrapFlag is TRUE, pointer to P7Data.
132 2) when WrapFlag is FALSE, pointer to a new ContentInfo
133 structure. It's caller's responsibility to free this
135 @param[out] WrapDataSize Length of ContentInfo structure in bytes.
137 @retval TRUE The operation is finished successfully.
138 @retval FALSE The operation is failed due to lack of resources.
143 IN CONST UINT8
*P7Data
,
145 OUT BOOLEAN
*WrapFlag
,
146 OUT UINT8
**WrapData
,
147 OUT UINTN
*WrapDataSize
154 // Check whether input P7Data is a wrapped ContentInfo structure or not.
157 if ((P7Data
[4] == 0x06) && (P7Data
[5] == 0x09)) {
158 if (CompareMem (P7Data
+ 6, mOidValue
, sizeof (mOidValue
)) == 0) {
159 if ((P7Data
[15] == 0xA0) && (P7Data
[16] == 0x82)) {
166 *WrapData
= (UINT8
*) P7Data
;
167 *WrapDataSize
= P7Length
;
170 // Wrap PKCS#7 signeddata to a ContentInfo structure - add a header in 19 bytes.
172 *WrapDataSize
= P7Length
+ 19;
173 *WrapData
= malloc (*WrapDataSize
);
174 if (*WrapData
== NULL
) {
179 SignedData
= *WrapData
;
182 // Part1: 0x30, 0x82.
184 SignedData
[0] = 0x30;
185 SignedData
[1] = 0x82;
188 // Part2: Length1 = P7Length + 19 - 4, in big endian.
190 SignedData
[2] = (UINT8
) (((UINT16
) (*WrapDataSize
- 4)) >> 8);
191 SignedData
[3] = (UINT8
) (((UINT16
) (*WrapDataSize
- 4)) & 0xff);
194 // Part3: 0x06, 0x09.
196 SignedData
[4] = 0x06;
197 SignedData
[5] = 0x09;
200 // Part4: OID value -- 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x07 0x02.
202 CopyMem (SignedData
+ 6, mOidValue
, sizeof (mOidValue
));
205 // Part5: 0xA0, 0x82.
207 SignedData
[15] = 0xA0;
208 SignedData
[16] = 0x82;
211 // Part6: Length2 = P7Length, in big endian.
213 SignedData
[17] = (UINT8
) (((UINT16
) P7Length
) >> 8);
214 SignedData
[18] = (UINT8
) (((UINT16
) P7Length
) & 0xff);
219 CopyMem (SignedData
+ 19, P7Data
, P7Length
);
227 Pop single certificate from STACK_OF(X509).
229 If X509Stack, Cert, or CertSize is NULL, then return FALSE.
231 @param[in] X509Stack Pointer to a X509 stack object.
232 @param[out] Cert Pointer to a X509 certificate.
233 @param[out] CertSize Length of output X509 certificate in bytes.
235 @retval TRUE The X509 stack pop succeeded.
236 @retval FALSE The pop operation failed.
248 STACK_OF(X509
) *CertStack
;
256 if ((X509Stack
== NULL
) || (Cert
== NULL
) || (CertSize
== NULL
)) {
260 CertStack
= (STACK_OF(X509
) *) X509Stack
;
262 X509Cert
= sk_X509_pop (CertStack
);
264 if (X509Cert
== NULL
) {
270 CertBio
= BIO_new (BIO_s_mem ());
271 if (CertBio
== NULL
) {
275 Result
= i2d_X509_bio (CertBio
, X509Cert
);
280 Length
= (INT32
)(((BUF_MEM
*) CertBio
->ptr
)->length
);
285 Buffer
= malloc (Length
);
286 if (Buffer
== NULL
) {
290 Result
= BIO_read (CertBio
, Buffer
, Length
);
291 if (Result
!= Length
) {
304 if (!Status
&& (Buffer
!= NULL
)) {
312 Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7:
313 Cryptographic Message Syntax Standard". The input signed data could be wrapped
314 in a ContentInfo structure.
316 If P7Data, CertStack, StackLength, TrustedCert or CertLength is NULL, then
317 return FALSE. If P7Length overflow, then return FALSE.
319 Caution: This function may receive untrusted input.
320 UEFI Authenticated Variable is external input, so this function will do basic
321 check for PKCS#7 data structure.
323 @param[in] P7Data Pointer to the PKCS#7 message to verify.
324 @param[in] P7Length Length of the PKCS#7 message in bytes.
325 @param[out] CertStack Pointer to Signer's certificates retrieved from P7Data.
326 It's caller's responsibility to free the buffer.
327 @param[out] StackLength Length of signer's certificates in bytes.
328 @param[out] TrustedCert Pointer to a trusted certificate from Signer's certificates.
329 It's caller's responsibility to free the buffer.
330 @param[out] CertLength Length of the trusted certificate in bytes.
332 @retval TRUE The operation is finished successfully.
333 @retval FALSE Error occurs during the operation.
339 IN CONST UINT8
*P7Data
,
341 OUT UINT8
**CertStack
,
342 OUT UINTN
*StackLength
,
343 OUT UINT8
**TrustedCert
,
344 OUT UINTN
*CertLength
351 UINTN SignedDataSize
;
353 STACK_OF(X509
) *Stack
;
360 UINTN SingleCertSize
;
362 if ((P7Data
== NULL
) || (CertStack
== NULL
) || (StackLength
== NULL
) ||
363 (TrustedCert
== NULL
) || (CertLength
== NULL
) || (P7Length
> INT_MAX
)) {
367 Status
= WrapPkcs7Data (P7Data
, P7Length
, &Wrapped
, &SignedData
, &SignedDataSize
);
380 // Retrieve PKCS#7 Data (DER encoding)
382 if (SignedDataSize
> INT_MAX
) {
387 Pkcs7
= d2i_PKCS7 (NULL
, (const unsigned char **) &Temp
, (int) SignedDataSize
);
393 // Check if it's PKCS#7 Signed Data (for Authenticode Scenario)
395 if (!PKCS7_type_is_signed (Pkcs7
)) {
399 Stack
= PKCS7_get0_signers(Pkcs7
, NULL
, PKCS7_BINARY
);
405 // Convert CertStack to buffer in following format:
407 // UINT32 Cert1Length;
409 // UINT32 Cert2Length;
412 // UINT32 CertnLength;
415 BufferSize
= sizeof (UINT8
);
416 OldSize
= BufferSize
;
418 for (Index
= 0; ; Index
++) {
419 Status
= X509PopCertificate (Stack
, &SingleCert
, &SingleCertSize
);
424 OldSize
= BufferSize
;
426 BufferSize
= OldSize
+ SingleCertSize
+ sizeof (UINT32
);
427 CertBuf
= malloc (BufferSize
);
429 if (CertBuf
== NULL
) {
433 if (OldBuf
!= NULL
) {
434 CopyMem (CertBuf
, OldBuf
, OldSize
);
439 WriteUnaligned32 ((UINT32
*) (CertBuf
+ OldSize
), (UINT32
) SingleCertSize
);
440 CopyMem (CertBuf
+ OldSize
+ sizeof (UINT32
), SingleCert
, SingleCertSize
);
446 if (CertBuf
!= NULL
) {
448 // Update CertNumber.
452 *CertLength
= BufferSize
- OldSize
- sizeof (UINT32
);
453 *TrustedCert
= malloc (*CertLength
);
454 if (*TrustedCert
== NULL
) {
458 CopyMem (*TrustedCert
, CertBuf
+ OldSize
+ sizeof (UINT32
), *CertLength
);
459 *CertStack
= CertBuf
;
460 *StackLength
= BufferSize
;
477 sk_X509_pop_free(Stack
, X509_free
);
480 if (SingleCert
!= NULL
) {
484 if (!Status
&& (CertBuf
!= NULL
)) {
489 if (OldBuf
!= NULL
) {
497 Wrap function to use free() to free allocated memory for certificates.
499 @param[in] Certs Pointer to the certificates to be freed.
516 Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7:
517 Cryptographic Message Syntax Standard", and outputs two certificate lists chained and
518 unchained to the signer's certificates.
519 The input signed data could be wrapped in a ContentInfo structure.
521 @param[in] P7Data Pointer to the PKCS#7 message.
522 @param[in] P7Length Length of the PKCS#7 message in bytes.
523 @param[out] SignerChainCerts Pointer to the certificates list chained to signer's
524 certificate. It's caller's responsibility to free the buffer.
525 @param[out] ChainLength Length of the chained certificates list buffer in bytes.
526 @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's
527 responsibility to free the buffer.
528 @param[out] UnchainLength Length of the unchained certificates list buffer in bytes.
530 @retval TRUE The operation is finished successfully.
531 @retval FALSE Error occurs during the operation.
536 Pkcs7GetCertificatesList (
537 IN CONST UINT8
*P7Data
,
539 OUT UINT8
**SignerChainCerts
,
540 OUT UINTN
*ChainLength
,
541 OUT UINT8
**UnchainCerts
,
542 OUT UINTN
*UnchainLength
551 X509_STORE_CTX CertCtx
;
552 STACK_OF(X509
) *Signers
;
577 ZeroMem (&CertCtx
, sizeof (CertCtx
));
580 // Parameter Checking
582 if ((P7Data
== NULL
) || (SignerChainCerts
== NULL
) || (ChainLength
== NULL
) ||
583 (UnchainCerts
== NULL
) || (UnchainLength
== NULL
) || (P7Length
> INT_MAX
)) {
587 *SignerChainCerts
= NULL
;
589 *UnchainCerts
= NULL
;
593 // Construct a new PKCS#7 data wrapping with ContentInfo structure if needed.
595 Status
= WrapPkcs7Data (P7Data
, P7Length
, &Wrapped
, &NewP7Data
, &NewP7Length
);
596 if (!Status
|| (NewP7Length
> INT_MAX
)) {
601 // Decodes PKCS#7 SignedData
603 Pkcs7
= d2i_PKCS7 (NULL
, (const unsigned char **) &NewP7Data
, (int) NewP7Length
);
604 if ((Pkcs7
== NULL
) || (!PKCS7_type_is_signed (Pkcs7
))) {
609 // Obtains Signer's Certificate from PKCS#7 data
610 // NOTE: Only one signer case will be handled in this function, which means SignerInfos
611 // should include only one signer's certificate.
613 Signers
= PKCS7_get0_signers (Pkcs7
, NULL
, PKCS7_BINARY
);
614 if ((Signers
== NULL
) || (sk_X509_num (Signers
) != 1)) {
617 Signer
= sk_X509_value (Signers
, 0);
619 if (!X509_STORE_CTX_init (&CertCtx
, NULL
, Signer
, Pkcs7
->d
.sign
->cert
)) {
623 // Initialize Chained & Untrusted stack
625 if (CertCtx
.chain
== NULL
) {
626 if (((CertCtx
.chain
= sk_X509_new_null ()) == NULL
) ||
627 (!sk_X509_push (CertCtx
.chain
, CertCtx
.cert
))) {
631 (VOID
)sk_X509_delete_ptr (CertCtx
.untrusted
, Signer
);
634 // Build certificates stack chained from Signer's certificate.
639 // Self-Issue checking
641 if (CertCtx
.check_issued (&CertCtx
, Cert
, Cert
)) {
646 // Found the issuer of the current certificate
648 if (CertCtx
.untrusted
!= NULL
) {
650 for (Index
= 0; Index
< sk_X509_num (CertCtx
.untrusted
); Index
++) {
651 TempCert
= sk_X509_value (CertCtx
.untrusted
, Index
);
652 if (CertCtx
.check_issued (&CertCtx
, Cert
, TempCert
)) {
657 if (Issuer
!= NULL
) {
658 if (!sk_X509_push (CertCtx
.chain
, Issuer
)) {
661 (VOID
)sk_X509_delete_ptr (CertCtx
.untrusted
, Issuer
);
672 // Converts Chained and Untrusted Certificate to Certificate Buffer in following format:
674 // UINT32 Cert1Length;
676 // UINT32 Cert2Length;
679 // UINT32 CertnLength;
683 if (CertCtx
.chain
!= NULL
) {
684 BufferSize
= sizeof (UINT8
);
685 OldSize
= BufferSize
;
688 for (Index
= 0; ; Index
++) {
689 Status
= X509PopCertificate (CertCtx
.chain
, &SingleCert
, &CertSize
);
694 OldSize
= BufferSize
;
696 BufferSize
= OldSize
+ CertSize
+ sizeof (UINT32
);
697 CertBuf
= malloc (BufferSize
);
699 if (CertBuf
== NULL
) {
703 if (OldBuf
!= NULL
) {
704 CopyMem (CertBuf
, OldBuf
, OldSize
);
709 WriteUnaligned32 ((UINT32
*) (CertBuf
+ OldSize
), (UINT32
) CertSize
);
710 CopyMem (CertBuf
+ OldSize
+ sizeof (UINT32
), SingleCert
, CertSize
);
716 if (CertBuf
!= NULL
) {
718 // Update CertNumber.
722 *SignerChainCerts
= CertBuf
;
723 *ChainLength
= BufferSize
;
727 if (CertCtx
.untrusted
!= NULL
) {
728 BufferSize
= sizeof (UINT8
);
729 OldSize
= BufferSize
;
732 for (Index
= 0; ; Index
++) {
733 Status
= X509PopCertificate (CertCtx
.untrusted
, &SingleCert
, &CertSize
);
738 OldSize
= BufferSize
;
740 BufferSize
= OldSize
+ CertSize
+ sizeof (UINT32
);
741 CertBuf
= malloc (BufferSize
);
743 if (CertBuf
== NULL
) {
747 if (OldBuf
!= NULL
) {
748 CopyMem (CertBuf
, OldBuf
, OldSize
);
753 WriteUnaligned32 ((UINT32
*) (CertBuf
+ OldSize
), (UINT32
) CertSize
);
754 CopyMem (CertBuf
+ OldSize
+ sizeof (UINT32
), SingleCert
, CertSize
);
760 if (CertBuf
!= NULL
) {
762 // Update CertNumber.
766 *UnchainCerts
= CertBuf
;
767 *UnchainLength
= BufferSize
;
775 // Release Resources.
777 if (!Wrapped
&& (NewP7Data
!= NULL
)) {
784 sk_X509_free (Signers
);
786 X509_STORE_CTX_cleanup (&CertCtx
);
788 if (SingleCert
!= NULL
) {
792 if (OldBuf
!= NULL
) {
796 if (!Status
&& (CertBuf
!= NULL
)) {
798 *SignerChainCerts
= NULL
;
799 *UnchainCerts
= NULL
;
806 Verifies the validity of a PKCS#7 signed data as described in "PKCS #7:
807 Cryptographic Message Syntax Standard". The input signed data could be wrapped
808 in a ContentInfo structure.
810 If P7Data, TrustedCert or InData is NULL, then return FALSE.
811 If P7Length, CertLength or DataLength overflow, then return FALSE.
813 Caution: This function may receive untrusted input.
814 UEFI Authenticated Variable is external input, so this function will do basic
815 check for PKCS#7 data structure.
817 @param[in] P7Data Pointer to the PKCS#7 message to verify.
818 @param[in] P7Length Length of the PKCS#7 message in bytes.
819 @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which
820 is used for certificate chain verification.
821 @param[in] CertLength Length of the trusted certificate in bytes.
822 @param[in] InData Pointer to the content to be verified.
823 @param[in] DataLength Length of InData in bytes.
825 @retval TRUE The specified PKCS#7 signed data is valid.
826 @retval FALSE Invalid PKCS#7 signed data.
832 IN CONST UINT8
*P7Data
,
834 IN CONST UINT8
*TrustedCert
,
836 IN CONST UINT8
*InData
,
844 X509_STORE
*CertStore
;
847 UINTN SignedDataSize
;
851 // Check input parameters.
853 if (P7Data
== NULL
|| TrustedCert
== NULL
|| InData
== NULL
||
854 P7Length
> INT_MAX
|| CertLength
> INT_MAX
|| DataLength
> INT_MAX
) {
864 // Register & Initialize necessary digest algorithms for PKCS#7 Handling
866 if (EVP_add_digest (EVP_md5 ()) == 0) {
869 if (EVP_add_digest (EVP_sha1 ()) == 0) {
872 if (EVP_add_digest (EVP_sha256 ()) == 0) {
875 if (EVP_add_digest (EVP_sha384 ()) == 0) {
878 if (EVP_add_digest (EVP_sha512 ()) == 0) {
881 if (EVP_add_digest_alias (SN_sha1WithRSAEncryption
, SN_sha1WithRSA
) == 0) {
885 Status
= WrapPkcs7Data (P7Data
, P7Length
, &Wrapped
, &SignedData
, &SignedDataSize
);
893 // Retrieve PKCS#7 Data (DER encoding)
895 if (SignedDataSize
> INT_MAX
) {
900 Pkcs7
= d2i_PKCS7 (NULL
, (const unsigned char **) &Temp
, (int) SignedDataSize
);
906 // Check if it's PKCS#7 Signed Data (for Authenticode Scenario)
908 if (!PKCS7_type_is_signed (Pkcs7
)) {
913 // Read DER-encoded root certificate and Construct X509 Certificate
916 Cert
= d2i_X509 (NULL
, &Temp
, (long) CertLength
);
922 // Setup X509 Store for trusted certificate
924 CertStore
= X509_STORE_new ();
925 if (CertStore
== NULL
) {
928 if (!(X509_STORE_add_cert (CertStore
, Cert
))) {
932 X509_STORE_set_verify_cb (CertStore
, X509VerifyCb
);
935 // For generic PKCS#7 handling, InData may be NULL if the content is present
936 // in PKCS#7 structure. So ignore NULL checking here.
938 DataBio
= BIO_new (BIO_s_mem ());
939 if (DataBio
== NULL
) {
943 if (BIO_write (DataBio
, InData
, (int) DataLength
) <= 0) {
948 // Allow partial certificate chains, terminated by a non-self-signed but
949 // still trusted intermediate certificate. Also disable time checks.
951 X509_STORE_set_flags (CertStore
,
952 X509_V_FLAG_PARTIAL_CHAIN
| X509_V_FLAG_NO_CHECK_TIME
);
955 // OpenSSL PKCS7 Verification by default checks for SMIME (email signing) and
956 // doesn't support the extended key usage for Authenticode Code Signing.
957 // Bypass the certificate purpose checking by enabling any purposes setting.
959 X509_STORE_set_purpose (CertStore
, X509_PURPOSE_ANY
);
962 // Verifies the PKCS#7 signedData structure
964 Status
= (BOOLEAN
) PKCS7_verify (Pkcs7
, NULL
, CertStore
, DataBio
, NULL
, PKCS7_BINARY
);
972 X509_STORE_free (CertStore
);
976 OPENSSL_free (SignedData
);
983 Extracts the attached content from a PKCS#7 signed data if existed. The input signed
984 data could be wrapped in a ContentInfo structure.
986 If P7Data, Content, or ContentSize is NULL, then return FALSE. If P7Length overflow,
987 then return FALSE. If the P7Data is not correctly formatted, then return FALSE.
989 Caution: This function may receive untrusted input. So this function will do
990 basic check for PKCS#7 data structure.
992 @param[in] P7Data Pointer to the PKCS#7 signed data to process.
993 @param[in] P7Length Length of the PKCS#7 signed data in bytes.
994 @param[out] Content Pointer to the extracted content from the PKCS#7 signedData.
995 It's caller's responsibility to free the buffer.
996 @param[out] ContentSize The size of the extracted content in bytes.
998 @retval TRUE The P7Data was correctly formatted for processing.
999 @retval FALSE The P7Data was not correctly formatted for processing.
1004 Pkcs7GetAttachedContent (
1005 IN CONST UINT8
*P7Data
,
1008 OUT UINTN
*ContentSize
1014 UINTN SignedDataSize
;
1017 ASN1_OCTET_STRING
*OctStr
;
1020 // Check input parameter.
1022 if ((P7Data
== NULL
) || (P7Length
> INT_MAX
) || (Content
== NULL
) || (ContentSize
== NULL
)) {
1031 Status
= WrapPkcs7Data (P7Data
, P7Length
, &Wrapped
, &SignedData
, &SignedDataSize
);
1032 if (!Status
|| (SignedDataSize
> INT_MAX
)) {
1039 // Decoding PKCS#7 SignedData
1042 Pkcs7
= d2i_PKCS7 (NULL
, (const unsigned char **)&Temp
, (int)SignedDataSize
);
1043 if (Pkcs7
== NULL
) {
1048 // The type of Pkcs7 must be signedData
1050 if (!PKCS7_type_is_signed (Pkcs7
)) {
1055 // Check for detached or attached content
1057 if (PKCS7_get_detached (Pkcs7
)) {
1059 // No Content supplied for PKCS7 detached signedData
1065 // Retrieve the attached content in PKCS7 signedData
1067 OctStr
= Pkcs7
->d
.sign
->contents
->d
.data
;
1068 if ((OctStr
->length
> 0) && (OctStr
->data
!= NULL
)) {
1069 *ContentSize
= OctStr
->length
;
1070 *Content
= malloc (*ContentSize
);
1071 if (*Content
== NULL
) {
1075 CopyMem (*Content
, OctStr
->data
, *ContentSize
);
1082 // Release Resources
1087 OPENSSL_free (SignedData
);