libressl-PKCS7_dataInit3
Construct a bio chain for adding or retrieving content
Usage
Crypto Library (libcrypto, -lcrypto)
#include <openssl/pkcs7.h>
BIO *
PKCS7_dataInit(PKCS7 *p7, BIO *indata);
Overview
PKCS7_dataInit() constructs a BIO chain in preparation for putting data into or retrieving data out of p7. Depending on the contentType of p7, the created chain starts with:
- for SignedData:
-
one or more BIO_f_md(3) message digest filters
- for EnvelopedData:
-
one BIO_f_cipher(3) encryption filter
- for SignedAndEnvelopedData:
-
one or more BIO_f_md(3) message digest filters followed by one BIO_f_cipher(3) encryption filter
- for DigestedData:
-
one BIO_f_md(3) message digest filter
- for arbitrary data:
-
no filter BIO
One additional BIO is appended to the end of the chain, depending on the first condition that holds in the following list:
- indata
-
if the indata argument is not NULL. This only makes sense while verifying a detached signature, in which case indata is expected to supply the content associated with the detached signature.
- BIO_s_null(3)
-
if the contentType of p7 is SignedData and it is configured to contain a detached signature. This only makes sense while creating the detached signature.
- BIO_new_mem_buf(3)
-
when reading from a SignedData or DigestedData object.
PKCS7_dataInit() attaches the end of the chain to the nested content of p7. - BIO_s_mem(3)
-
otherwise. This is the most common case while writing data to p7. PKCS7_dataFinal(3) can later be used to transfer the data from the memory BIO into p7.
Adding content
Before calling PKCS7_dataInit() in order to add content, PKCS7_new(3), PKCS7_set_type(3), and PKCS7_content_new(3) are typically required to create p7, to choose its desired type, and to allocate the nested ContentInfo structure. Alternatively, for SignedData, PKCS7_sign(3) can be used with the PKCS7_PARTIAL or PKCS7_STREAM flags or for EnvelopedData, PKCS7_encrypt(3) with the PKCS7_STREAM flag.
After calling PKCS7_dataInit(), the desired data can be written into the returned BIO, BIO_flush(3) can be called on it, PKCS7_dataFinal(3) can be used to transfer the processed data from the returned memory BIO to the p7 structure, and the chain can finally be destroyed with BIO_free_all(3).
While PKCS7_dataInit() does support the EnvelopedData and SignedAndEnvelopedData types, using it for these types is awkward and error prone except when using PKCS7_encrypt(3) for the setup because PKCS7_content_new(3) does not support these two types. So in addition to creating p7 itself and setting its type, the nested ContentInfo structure also needs to be constructed with PKCS7_new(3) and PKCS7_set_type(3) and manually inserted into the correct field of the respective sub-structure of p7.
Retrieving content
PKCS7_dataInit() can also be called on a fully populated object of type SignedData or DigestedData. After that, BIO_read(3) can be used to retrieve data from it. In this use case, do not call PKCS7_dataFinal(3); simply proceed directly to BIO_free_all(3) after reading the data.
Return values
PKCS7_dataInit() returns a BIO chain on success or NULL on failure. It fails if p7 is NULL, if the content field of p7 is empty, if the contentType of p7 is unsupported, if a cipher is required but none is configured, or if any required operation fails, for example due to lack of memory or for various other reasons.
Caveats
This function does not support EncryptedData.