libressl-PKCS7_dataInit(3)

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.

History

PKCS7_dataInit() first appeared in SSLeay 0.8.1 and has been available since OpenBSD 2.4.

Bugs

If p7 is a fully populated structure containing EnvelopedData, SignedAndEnvelopedData, or arbitrary data, PKCS7_dataInit() returns a BIO chain that ultimately reads from an empty memory BIO, so reading from it will instantly return an end-of-file indication rather than reading the actual data contained in p7.

From libressl 4.4.0-1 in Arch Linux 2026-11-01. Parsed by carta from the page's mdoc source.