TrustCore SDK NanoCrypto API reference  version 7.0

PKCS \#7 Overview

Note
RFC 2315 has been superceded by more recent RFCs. As of this document's writing (for SoT Platform 6.4), the most recent RFC is RFC 5652. The objects defined in RFC 5652 are different from the objects defined in RFC 2315. If you are working with RFC 5632 objects, use the functions that are documented in cms.dxd (for functions declared and defined in in cms.h and cms.inc). The cms.{h,inc} API is included in pkcs7.c if the __ENABLE_MOCANA_CMS__ and __ENABLE_MOCANA_PKCS7__ flags are defined in moptions.h.

Using ContentInfo objects in PKCS #7 messages, the participants in a conversation can exchange simple data objects, signed data objects, enveloped data objects, and so on. This file's API lets you create, parse, and otherwise manage these ContentInfo objects.

Note
This API does not include functions for managing simple data objects, which RFC 2315 defines as simple OCTET STRING objects.

About RFC 2315 Objects

ContentInfo Object
RFC 2315 defines a ContentInfo object as:

    ContentInfo ::= SEQUENCE {
        contentType ContentType,
        content
            [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
    ContentType ::= OBJECT IDENTIFIER

The ContentType OBJECT_IDENTIFIER is defined in Section 14 of RFC 2315 as:

    data OBJECT IDENTIFIER ::= { pkcs-7 1 }
        signedData OBJECT IDENTIFIER ::= { pkcs-7 2 }
        envelopedData OBJECT IDENTIFIER ::= { pkcs-7 3 }
        signedAndEnvelopedData OBJECT IDENTIFIER ::= { pkcs-7 4 }
        digestedData OBJECT IDENTIFIER ::= { pkcs-7 5 }
        encryptedData OBJECT IDENTIFIER ::= { pkcs-7 6 }
EnvelopedData Ojbect
RFC 2315 defines the EnvelopedData object as follows:

    EnvelopedData ::= SEQUENCE {
        version Version,
        recipientInfos RecipientInfos,
        encryptedContentInfo EncryptedContentInfo }
    RecipientInfos ::= SET OF RecipientInfo
    EncryptedContentInfo ::= SEQUENCE {
        contentType ContentType,
        contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
        encryptedContent[0] IMPLICIT EncryptedContent OPTIONAL }
    EncryptedContent ::= OCTET STRING
    RecipientInfo ::= SEQUENCE {
        version Version,
        issuerAndSerialNumber IssuerAndSerialNumber,
        keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
        encryptedKey EncryptedKey }
    EncryptedKey ::= OCTET STRING

To populate a ContentType object with an EnvelopedData object, use code similar to the following:

DER_ITEMPTR pContentInfo=NULL, pEnvelopedData;
DER_AddSequence(NULL, &pContentInfo);
DER_AddOID(pContentInfo, pkcs7_envelopedData_OID, NULL);
DER_AddTag(pContentInfo, 0, &pEnvelopedData);
SignedData Object
RFC 2315 defines the SignedData object as follows:

    SignedData ::= SEQUENCE {
        version Version,
        digestAlgorithms DigestAlgorithmIdentifiers,
        contentInfo ContentInfo,
        certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
        crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
        signerInfos SignerInfos }
    DigestAlgorithmIdentifiers ::=
        SET OF DigestAlgorithmIdentifier
        SignerInfos ::= SET OF SignerInfo
        SignerInfo ::= SEQUENCE {
            version Version,
            issuerAndSerialNumber IssuerAndSerialNumber,
            digestAlgorithm DigestAlgorithmIdentifier,
            authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
            digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
            encryptedDigest EncryptedDigest,
            unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL }
    EncryptedDigest ::= OCTET STRING

To populate a ContentType object with a SignedData object, use code similar to the following:

DER_ITEMPTR pContentInfo=NULL, pSignedData;
DER_AddSequence(NULL, &pContentInfo);
DER_AddOID(pContentInfo, pkcs7_signedData_OID, NULL);
DER_AddTag(pContentInfo, 0, &pSignedData);
DigestedData Object
RFC 2315 defines the DigestedData object as follows:

    DigestedData ::= SEQUENCE {
        version Version,
        digestAlgorithm DigestAlgorithmIdentifier,
        contentInfo ContentInfo,
        digest Digest }
        Digest ::= OCTET STRING
        ContentInfo ::= SEQUENCE {
            contentType ContentType,
            content
                [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }

To populate a ContentType object with a DigestedData object, use code similar to the following:

DER_ITEMPTR pDigestedInfo=NULL, pDigestedData;
DER_AddSequence(NULL, &pDigestedInfo);
DER_AddOID(pDigestedInfo, pkcs7_digestedData_OID, NULL);
DER_AddTag(pDigestedInfo, 0, &pDigestedData);
SignerInfo Object
RFC 2315 defines the SignerInfo object as follows:

    SignerInfo ::= SEQUENCE {
        version Version,
        issuerAndSerialNumber IssuerAndSerialNumber,
        digestAlgorithm DigestAlgorithmIdentifier,
        authenticatedAttributes
            [0] IMPLICIT Attributes OPTIONAL,
        digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
        encryptedDigest EncryptedDigest,
        unauthenticatedAttributes
           [1] IMPLICIT Attributes OPTIONAL }
    EncryptedDigest ::= OCTET STRING

Structures

The PKCS #7 API defines the following structures and structure pointer:

  • Attribute, a structure that stores attribute information for a SignedData object.
  • signerInfo, a structure that stores information for a SignedData object.
  • signerInfoPtr, a pointer to a signerInfo structure.
  • PKCS7_Callbacks, stores the PKCS #7 callbacks required by the SoT Platform PKCS #12 convenience API.

Setting up a CStream and Getting the ASN1_ITEM for the Root ASN.1 Object

A CStream contains a memory-resident DER-encoded ASN.1 object, which is an inconvenient object from which to extract data or to which to add data. However, you can call ASN1_Parse() for a CStream to parse the CStream and create a tree of ASN1_ITEM structures that maps out the content of the CStream. ASN1_Parse() also provides a pointer to the address of the root ASN1_ITEM structure in this tree.
Note
The ASN1_ITEM structures returned from ASN1_Parse() do not store data extracted from the CStream. Instead, the structures store offsets and data lengths that you can use to find specific content in the CStream.

To set up a CStream and parse it, use code modeled on the following:

ubyte* signedDataFile = FILE_PATH("myDerEncodedSignedDataFile.der");
ubyte *pSignedDataFile=NULL;
ubyte4 signedDataFileLen;
CStream s;
MemFile memFile;
ASN1_ITEMPTR pRootItem=NULL;
if (OK > (status = MOCANA_readFile(signedDataFile, &pSignedDataFile,
&signedDataFileLen)))
{ handle error }
MF_attach(&memFile, signedDataFileLen, (ubyte*) pSignedDataFile);
CS_AttachMemFile(&s, &memFile );
if (OK > (status = ASN1_Parse(s, &pRootItem)))
{ handle error }
This code snippet creates a CStream for a SignedData object. However, this code is not specific to any given object type. Depending on the content of the file that is read, the code could create a CStream containing an enveloped data object (EnvelopedData), a signed and enveloped data object (SignedObject), a digested data object, or an encrypted data object. Therefore, you must change the code snippet's variable names to accurately indicate their content.
Warning
The preceding code snippet contains memory leaks. In your code, be sure to call MOCANA_freeReadFile() to free the allocated memory.