|
Leancrypto 1.6.0
Post-Quantum Cryptographic Library
|
Macros | |
| #define | LC_PKCS7_MSG_SIZE(num_sinfo, num_x509) |
| Size of pre-allocated PKCS7 message. | |
| #define | LC_PKCS7_MSG_ON_STACK(name, num_sinfo, num_x509) |
| Allocate memory for struct lc_pkcs7_message holding given number of preallocated sinfo members. | |
Functions | |
| int | lc_pkcs7_decode (struct lc_pkcs7_message *pkcs7, const uint8_t *data, size_t datalen) |
| Decode a PKCS#7 message. | |
| void | lc_pkcs7_message_clear (struct lc_pkcs7_message *pkcs7) |
| Clear the resources used by the PKCS#7 message parsing state. | |
| int | lc_pkcs7_get_content_data (const struct lc_pkcs7_message *pkcs7, const uint8_t **data, size_t *datalen) |
| Get access to the PKCS#7 encapsulated content. | |
| int | lc_pkcs7_verify (struct lc_pkcs7_message *pkcs7, const struct lc_pkcs7_trust_store *trust_store, const struct lc_verify_rules *verify_rules) |
| Verify a PKCS#7 message. | |
| int | lc_pkcs7_supply_detached_data (struct lc_pkcs7_message *pkcs7, const uint8_t *data, size_t datalen) |
| Supply the data needed to verify a PKCS#7 message. | |
| int | lc_pkcs7_get_digest (struct lc_pkcs7_message *pkcs7, const uint8_t **message_digest, size_t *message_digest_len, const struct lc_hash **hash_algo) |
| Calculate and return the message digest of the data. | |
| int | lc_pkcs7_trust_store_add (struct lc_pkcs7_trust_store *trust_store, struct lc_x509_certificate *x509) |
| Add a certificate to a certificate trust store. | |
| void | lc_pkcs7_trust_store_clear (struct lc_pkcs7_trust_store *trust_store) |
| Release and clear the trust store. | |
Concept of PKCS#7 parsing in leancrypto
The leancrypto library provides a PKCS#7 parser which can read and understand PKCS#7 messages. To appropriately use the PKCS#7 parser, please consider the following rules:
pkcs7_message is provided as part of the official header file. But it is NOT considered to be an API. I.e. member variables or the structure format may change between versions of leancrypto without announcement. The reason for providing the data structure in the official header file is to support stack-only clients. Aas a PKCS#7 message may contain an arbitrary amount of X.509 certificates and signer information sections, the macro LC_PKCS7_MSG_ON_STACK is provided to allocate stack memory for a given number of signers and X.509 certificates. If more certificates or signers are found, heap is transparently allocated.pkcs7_message data structure.The PKCS#7 message parser currently only covers signature verification to support use cases of secure boot.
For performing a proper PKCS#7 validation, execute the following steps:
Initialize and load the certificate trust store by executing the following sub tasks. This assumes that each trusted public key is represented as an X.509 certificate which implies the set of sub steps must be executed for each certificate that shall be part of the trust store.
a. Load the X.509 data blob with lc_x509_certificate_parse
b. Register the certificate in the PKCS#7 trust store with lc_pkcs7_trust_anchor_add
lc_pkcs7_message_parse.lc_pkcs7_verify. | #define LC_PKCS7_MSG_ON_STACK | ( | name, | |
| num_sinfo, | |||
| num_x509 ) |
Allocate memory for struct lc_pkcs7_message holding given number of preallocated sinfo members.
This allocation allows the PKCS7 parsing to avoid allocate memory and keep all operations on stack. In case more signers than num_sinfo or more X.509 certificates than num_x509 are parsed from the PKCS7 message, then first all pre-allocated structures are used and then new ones are allocated.
When not using this macro, which is perfectly legal, an simply allocating struct lc_pkcs7_message on stack, then for all parsed signers and X.509 certificates, a new memory entry is allocated.
Zeroize the data structure with the size provided by LC_PKCS7_MSG_SIZE.
| [in] | name | Name of stack variable |
| [in] | num_sinfo | Number of preallocated sinfo members (must be less than 256) |
| [in] | num_x509 | Number of preallocated X.509 certificate structures (must be less than 256) |
Definition at line 151 of file lc_pkcs7_common.h.
| #define LC_PKCS7_MSG_SIZE | ( | num_sinfo, | |
| num_x509 ) |
Size of pre-allocated PKCS7 message.
| [in] | num_sinfo | Number of preallocated sinfo members (must be less than 256) |
| [in] | num_x509 | Number of preallocated X.509 certificate structures (must be less than 256) |
Definition at line 123 of file lc_pkcs7_common.h.
| int lc_pkcs7_decode | ( | struct lc_pkcs7_message * | pkcs7, |
| const uint8_t * | data, | ||
| size_t | datalen ) |
Decode a PKCS#7 message.
The function parses a PKCS#7 data buffer into a data structure that allows accessing the various data points of the PKCS#7 message.
pkcs7 data structure will contain pointers to the data buffer. I.e. the message parsing analyzes data and finds all relevant data in the raw X.509 data blob. The caller MUST therefore keep the data pointer constant as long as the pkcs7 pointer is valid.| [in,out] | pkcs7 | The data structure that is filled with all parameters from the PKCS#7 message data buffer. The buffer must have been allocated by the caller. It is permissible to keep it on the stack. |
| [in] | data | Raw PKCS#7 data blob following RFC5652 |
| [in] | datalen | Length of the raw PKCS#7 message buffer |
| int lc_pkcs7_get_content_data | ( | const struct lc_pkcs7_message * | pkcs7, |
| const uint8_t ** | data, | ||
| size_t * | datalen ) |
Get access to the PKCS#7 encapsulated content.
Get access to the data content of the PKCS#7 message. The size of the header of the ASN.1 object that contains it is also provided and can be used to adjust *data and *data_len to get the entire object.
| [in] | pkcs7 | The preparsed PKCS#7 message to access |
| [out] | data | Place to return a pointer to the data |
| [out] | datalen | Place to return the data length |
| int lc_pkcs7_get_digest | ( | struct lc_pkcs7_message * | pkcs7, |
| const uint8_t ** | message_digest, | ||
| size_t * | message_digest_len, | ||
| const struct lc_hash ** | hash_algo ) |
Calculate and return the message digest of the data.
Using the PKCS#7 message, calculate the message digest of the data encapsulated by the PKCS#7 structure and return the message digest. It uses the message digest algorithm defined by the PKCS#7 structure. Optionally the function returns the used hash algorithm.
pkcs7 data structure. It has the same life time as this structure and thus should not be freed or modified.| [in] | pkcs7 | The PKCS#7 message with the encapsulated data |
| [out] | message_digest | Pointer to the message digest returned to the caller |
| [out] | message_digest_len | Length of the message digest returned to the caller |
| [out] | hash_algo | Reference to used hash algorithm (if the caller supplies NULL, no data is returned) |
| void lc_pkcs7_message_clear | ( | struct lc_pkcs7_message * | pkcs7 | ) |
Clear the resources used by the PKCS#7 message parsing state.
| [in] | pkcs7 | Certificate structure to be cleared |
| int lc_pkcs7_supply_detached_data | ( | struct lc_pkcs7_message * | pkcs7, |
| const uint8_t * | data, | ||
| size_t | datalen ) |
Supply the data needed to verify a PKCS#7 message.
Supply the detached data needed to verify a PKCS#7 message. Note that no attempt to retain/pin the data is made. That is left to the caller. The data will not be modified by pkcs7_verify() and will not be freed when the PKCS#7 message is freed.
| [in] | pkcs7 | The PKCS#7 message |
| [in] | data | The data to be verified |
| [in] | datalen | The amount of data |
| int lc_pkcs7_trust_store_add | ( | struct lc_pkcs7_trust_store * | trust_store, |
| struct lc_x509_certificate * | x509 ) |
Add a certificate to a certificate trust store.
The caller provides the trust_store which may be empty at the beginning. The function initializes the trust store and registers the certificate as a trusted certificate.
This function can be called repeatedly with the same trust store to add an arbitrary number of X.509 certificates.
Only certificates marked as CAs are allowed to be registered in the trust store.
It is permissible to load intermediate certificates. But the loading of such intermediate certificate requires the presence of the certificate chain leading to the associated root CA.
| [in] | trust_store | Trust store to add the certificate to |
| [in] | x509 | Certificate to be added to trust store |
| void lc_pkcs7_trust_store_clear | ( | struct lc_pkcs7_trust_store * | trust_store | ) |
Release and clear the trust store.
| [in] | trust_store | Trust store be released |
| int lc_pkcs7_verify | ( | struct lc_pkcs7_message * | pkcs7, |
| const struct lc_pkcs7_trust_store * | trust_store, | ||
| const struct lc_verify_rules * | verify_rules ) |
Verify a PKCS#7 message.
Verify a PKCS#7 message is internally consistent - that is, the data digest matches the digest in the AuthAttrs and any signature in the message or one of the X.509 certificates it carries that matches another X.509 cert in the message can be verified.
If a trust_store is provided, perform the certificate validation also against this trust store to find intermediate or root CA certificates. The final certificate of a certificate chain must end in a root CA certificate which must also be present in the trust_store.
The validation against the trust_store checks that the certificate chains inside the PKCS#7 message intersects keys we already know and trust. I.e. at least one certificate chain must lead to the trust_store.
lc_pkcs7_supply_detached_data to refer to this detached data before the lc_pkcs7_verify can be executed.| [in] | pkcs7 | The PKCS#7 message to be verified |
| [in] | trust_store | Trust store with trust anchor certificates - it MAY be NULL which implies that no check against the a trust anchor store is performed. In this case, the presence of a root certificate is considered sufficient. |
| [in] | verify_rules | If non-NULL, the given rules are applied during certificate verification. |
Returns, in order of descending priority:
(*) -EKEYREJECTED if a key was selected that had a usage restriction at odds with the specified usage, or:
(*) -EKEYREJECTED if a signature failed to match for which we found an appropriate X.509 certificate, or:
(*) -EBADMSG if some part of the message was invalid, or:
(*) 0 if a signature chain passed verification, or:
(*) -EKEYREJECTED if a blacklisted key was encountered, or:
(*) -ENOPKG if none of the signature chains are verifiable because suitable crypto modules couldn't be found.