#include <Security/SecCmsContentInfo.h>
#include <Security/SecCmsDigestContext.h>
#include <Security/SecCmsDigestedData.h>
#include <Security/SecCmsEncryptedData.h>
#include <Security/SecCmsEnvelopedData.h>
#include <Security/SecCmsSignedData.h>
#include "cmslocal.h"
#include "secoid.h"
#include "secitem.h"
#include <security_asn1/secerr.h>
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
void
SecCmsContentInfoDestroy(SecCmsContentInfoRef cinfo)
{
SECOidTag kind;
kind = SecCmsContentInfoGetContentTypeTag(cinfo);
switch (kind) {
case SEC_OID_PKCS7_ENVELOPED_DATA:
SecCmsEnvelopedDataDestroy(cinfo->content.envelopedData);
break;
case SEC_OID_PKCS7_SIGNED_DATA:
SecCmsSignedDataDestroy(cinfo->content.signedData);
break;
case SEC_OID_PKCS7_ENCRYPTED_DATA:
SecCmsEncryptedDataDestroy(cinfo->content.encryptedData);
break;
case SEC_OID_PKCS7_DIGESTED_DATA:
SecCmsDigestedDataDestroy(cinfo->content.digestedData);
break;
default:
break;
}
if (cinfo->digcx) {
SecCmsDigestContextCancel(cinfo->digcx);
cinfo->digcx = NULL;
}
if (cinfo->bulkkey)
CFRelease(cinfo->bulkkey);
if (cinfo->privkey)
CFRelease(cinfo->privkey);
if (cinfo->ciphcx) {
SecCmsCipherContextDestroy(cinfo->ciphcx);
cinfo->ciphcx = NULL;
}
}
SecCmsContentInfoRef
SecCmsContentInfoGetChildContentInfo(SecCmsContentInfoRef cinfo)
{
void *ptr = NULL;
SecCmsContentInfoRef ccinfo = NULL;
SECOidTag tag = SecCmsContentInfoGetContentTypeTag(cinfo);
switch (tag) {
case SEC_OID_PKCS7_SIGNED_DATA:
ptr = (void *)cinfo->content.signedData;
ccinfo = &(cinfo->content.signedData->contentInfo);
break;
case SEC_OID_PKCS7_ENVELOPED_DATA:
ptr = (void *)cinfo->content.envelopedData;
ccinfo = &(cinfo->content.envelopedData->contentInfo);
break;
case SEC_OID_PKCS7_DIGESTED_DATA:
ptr = (void *)cinfo->content.digestedData;
ccinfo = &(cinfo->content.digestedData->contentInfo);
break;
case SEC_OID_PKCS7_ENCRYPTED_DATA:
ptr = (void *)cinfo->content.encryptedData;
ccinfo = &(cinfo->content.encryptedData->contentInfo);
break;
case SEC_OID_PKCS7_DATA:
case SEC_OID_OTHER:
default:
break;
}
return (ptr ? ccinfo : NULL);
}
OSStatus
SecCmsContentInfoSetContent(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SECOidTag type, void *ptr)
{
OSStatus rv;
cinfo->contentTypeTag = SECOID_FindOIDByTag(type);
if (cinfo->contentTypeTag == NULL)
return paramErr;
rv = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentType), &(cinfo->contentTypeTag->oid));
if (rv != SECSuccess)
return memFullErr;
cinfo->content.pointer = ptr;
if (type != SEC_OID_PKCS7_DATA) {
cinfo->rawContent = SECITEM_AllocItem(cmsg->poolp, NULL, 1);
if (cinfo->rawContent == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return memFullErr;
}
}
return noErr;
}
OSStatus
SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached)
{
if (SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess)
return PORT_GetError();
cinfo->rawContent = (detached) ?
NULL : (data) ?
data : SECITEM_AllocItem(cmsg->poolp, NULL, 1);
return noErr;
}
OSStatus
SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd)
{
return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_SIGNED_DATA, (void *)sigd);
}
OSStatus
SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd)
{
return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_ENVELOPED_DATA, (void *)envd);
}
OSStatus
SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd)
{
return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_DIGESTED_DATA, (void *)digd);
}
OSStatus
SecCmsContentInfoSetContentEncryptedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd)
{
return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd);
}
OSStatus
SecCmsContentInfoSetContentOther(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached, const CSSM_OID *eContentType)
{
SECStatus srtn;
SECOidData *tmpOidData;
srtn = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentType), eContentType);
if (srtn != SECSuccess) {
return memFullErr;
}
tmpOidData = SECOID_FindOIDByTag(SEC_OID_OTHER);
cinfo->contentTypeTag = (SECOidData *)PORT_ArenaZAlloc(cmsg->poolp, sizeof(SECOidData));
*cinfo->contentTypeTag = *tmpOidData;
srtn = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentTypeTag->oid), eContentType);
if (srtn != SECSuccess) {
return memFullErr;
}
cinfo->content.pointer = data;
cinfo->rawContent = (detached) ?
NULL : (data) ?
data : SECITEM_AllocItem(cmsg->poolp, NULL, 1);
return noErr;
}
void *
SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo)
{
SECOidTag tag = (cinfo && cinfo->contentTypeTag)
? cinfo->contentTypeTag->offset
: cinfo->contentType.Data ? SEC_OID_OTHER : SEC_OID_UNKNOWN;
switch (tag) {
case SEC_OID_PKCS7_DATA:
case SEC_OID_PKCS7_SIGNED_DATA:
case SEC_OID_PKCS7_ENVELOPED_DATA:
case SEC_OID_PKCS7_DIGESTED_DATA:
case SEC_OID_PKCS7_ENCRYPTED_DATA:
case SEC_OID_OTHER:
return cinfo->content.pointer;
default:
return NULL;
}
}
CSSM_DATA_PTR
SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo)
{
SECOidTag tag;
for(;;) {
tag = SecCmsContentInfoGetContentTypeTag(cinfo);
switch (tag) {
case SEC_OID_PKCS7_DATA:
case SEC_OID_OTHER:
return cinfo->content.data;
case SEC_OID_PKCS7_DIGESTED_DATA:
case SEC_OID_PKCS7_ENCRYPTED_DATA:
case SEC_OID_PKCS7_ENVELOPED_DATA:
case SEC_OID_PKCS7_SIGNED_DATA:
cinfo = SecCmsContentInfoGetChildContentInfo(cinfo);
if (cinfo == NULL) {
return NULL;
}
break;
case SEC_OID_PKCS9_ID_CT_TSTInfo:
return cinfo->rawContent;
default:
PORT_Assert(0);
return NULL;
}
}
return NULL;
}
SECOidTag
SecCmsContentInfoGetContentTypeTag(SecCmsContentInfoRef cinfo)
{
if (cinfo->contentTypeTag == NULL)
cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
if (cinfo->contentTypeTag == NULL)
return SEC_OID_OTHER;
return cinfo->contentTypeTag->offset;
}
CSSM_DATA_PTR
SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo)
{
if (cinfo->contentTypeTag == NULL)
cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
if (cinfo->contentTypeTag == NULL) {
if(cinfo->contentType.Data != NULL) {
return &cinfo->contentType;
}
else {
return NULL;
}
}
return &(cinfo->contentTypeTag->oid);
}
SECOidTag
SecCmsContentInfoGetContentEncAlgTag(SecCmsContentInfoRef cinfo)
{
if (cinfo->contentEncAlgTag == SEC_OID_UNKNOWN)
cinfo->contentEncAlgTag = SECOID_GetAlgorithmTag(&(cinfo->contentEncAlg));
return cinfo->contentEncAlgTag;
}
SECAlgorithmID *
SecCmsContentInfoGetContentEncAlg(SecCmsContentInfoRef cinfo)
{
return &(cinfo->contentEncAlg);
}
OSStatus
SecCmsContentInfoSetContentEncAlg(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo,
SECOidTag bulkalgtag, CSSM_DATA_PTR parameters, int keysize)
{
PLArenaPool *poolp = (PLArenaPool *)pool;
OSStatus rv;
rv = SECOID_SetAlgorithmID(poolp, &(cinfo->contentEncAlg), bulkalgtag, parameters);
if (rv != SECSuccess)
return SECFailure;
cinfo->keysize = keysize;
return SECSuccess;
}
OSStatus
SecCmsContentInfoSetContentEncAlgID(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo,
SECAlgorithmID *algid, int keysize)
{
PLArenaPool *poolp = (PLArenaPool *)pool;
OSStatus rv;
rv = SECOID_CopyAlgorithmID(poolp, &(cinfo->contentEncAlg), algid);
if (rv != SECSuccess)
return SECFailure;
if (keysize >= 0)
cinfo->keysize = keysize;
return SECSuccess;
}
void
SecCmsContentInfoSetBulkKey(SecCmsContentInfoRef cinfo, SecSymmetricKeyRef bulkkey)
{
const CSSM_KEY *cssmKey = NULL;
cinfo->bulkkey = bulkkey;
CFRetain(cinfo->bulkkey);
SecKeyGetCSSMKey(cinfo->bulkkey, &cssmKey);
cinfo->keysize = cssmKey ? cssmKey->KeyHeader.LogicalKeySizeInBits : 0;
}
SecSymmetricKeyRef
SecCmsContentInfoGetBulkKey(SecCmsContentInfoRef cinfo)
{
if (cinfo->bulkkey == NULL)
return NULL;
CFRetain(cinfo->bulkkey);
return cinfo->bulkkey;
}
int
SecCmsContentInfoGetBulkKeySize(SecCmsContentInfoRef cinfo)
{
return cinfo->keysize;
}