#include <Security/SecCmsMessage.h>
#include <Security/SecCmsContentInfo.h>
#include <Security/SecCmsSignedData.h>
#include "cmslocal.h"
#include "secitem.h"
#include "secoid.h"
#include <security_asn1/secasn1.h>
#include <security_asn1/secerr.h>
SecCmsMessageRef
SecCmsMessageCreate(SecArenaPoolRef pool)
{
PLArenaPool *poolp = (PLArenaPool *)pool;
void *mark = NULL;
SecCmsMessageRef cmsg = NULL;
Boolean poolp_is_ours = PR_FALSE;
if (poolp == NULL) {
poolp = PORT_NewArena (1024);
if (poolp == NULL)
return NULL;
poolp_is_ours = PR_TRUE;
}
if (!poolp_is_ours)
mark = PORT_ArenaMark(poolp);
cmsg = (SecCmsMessageRef)PORT_ArenaZAlloc (poolp, sizeof(SecCmsMessage));
if (cmsg == NULL) {
if (!poolp_is_ours) {
if (mark) {
PORT_ArenaRelease(poolp, mark);
}
} else
PORT_FreeArena(poolp, PR_FALSE);
return NULL;
}
cmsg->poolp = poolp;
cmsg->poolp_is_ours = poolp_is_ours;
cmsg->refCount = 1;
if (mark)
PORT_ArenaUnmark(poolp, mark);
return cmsg;
}
void
SecCmsMessageSetEncodingParams(SecCmsMessageRef cmsg,
PK11PasswordFunc pwfn, void *pwfn_arg,
SecCmsGetDecryptKeyCallback decrypt_key_cb, void *decrypt_key_cb_arg,
SECAlgorithmID **detached_digestalgs, CSSM_DATA_PTR *detached_digests)
{
#if 0
if (pwfn)
PK11_SetPasswordFunc(pwfn);
#endif
cmsg->pwfn_arg = pwfn_arg;
cmsg->decrypt_key_cb = decrypt_key_cb;
cmsg->decrypt_key_cb_arg = decrypt_key_cb_arg;
cmsg->detached_digestalgs = detached_digestalgs;
cmsg->detached_digests = detached_digests;
}
void
SecCmsMessageDestroy(SecCmsMessageRef cmsg)
{
PORT_Assert (cmsg->refCount > 0);
if (cmsg->refCount <= 0)
return;
cmsg->refCount--;
if (cmsg->refCount > 0)
return;
SecCmsContentInfoDestroy(&(cmsg->contentInfo));
if (cmsg->poolp_is_ours && cmsg->poolp) {
PORT_FreeArena (cmsg->poolp, PR_TRUE);
}
}
SecCmsMessageRef
SecCmsMessageCopy(SecCmsMessageRef cmsg)
{
if (cmsg == NULL)
return NULL;
PORT_Assert (cmsg->refCount > 0);
cmsg->refCount++;
return cmsg;
}
SecArenaPoolRef
SecCmsMessageGetArena(SecCmsMessageRef cmsg)
{
return (SecArenaPoolRef)cmsg->poolp;
}
SecCmsContentInfoRef
SecCmsMessageGetContentInfo(SecCmsMessageRef cmsg)
{
return &(cmsg->contentInfo);
}
CSSM_DATA_PTR
SecCmsMessageGetContent(SecCmsMessageRef cmsg)
{
SecCmsContentInfoRef cinfo = SecCmsMessageGetContentInfo(cmsg);
CSSM_DATA_PTR pItem = SecCmsContentInfoGetInnerContent(cinfo);
return pItem;
}
int
SecCmsMessageContentLevelCount(SecCmsMessageRef cmsg)
{
int count = 0;
SecCmsContentInfoRef cinfo;
for (cinfo = &(cmsg->contentInfo); cinfo != NULL; ) {
count++;
cinfo = SecCmsContentInfoGetChildContentInfo(cinfo);
}
return count;
}
SecCmsContentInfoRef
SecCmsMessageContentLevel(SecCmsMessageRef cmsg, int n)
{
int count = 0;
SecCmsContentInfoRef cinfo;
for (cinfo = &(cmsg->contentInfo); cinfo != NULL && count < n; cinfo = SecCmsContentInfoGetChildContentInfo(cinfo)) {
count++;
}
return cinfo;
}
Boolean
SecCmsMessageContainsCertsOrCrls(SecCmsMessageRef cmsg)
{
SecCmsContentInfoRef cinfo;
for (cinfo = &(cmsg->contentInfo); cinfo != NULL; cinfo = SecCmsContentInfoGetChildContentInfo(cinfo)) {
if (SecCmsContentInfoGetContentTypeTag(cinfo) != SEC_OID_PKCS7_SIGNED_DATA)
continue;
if (SecCmsSignedDataContainsCertsOrCrls(cinfo->content.signedData))
return PR_TRUE;
}
return PR_FALSE;
}
Boolean
SecCmsMessageIsEncrypted(SecCmsMessageRef cmsg)
{
SecCmsContentInfoRef cinfo;
for (cinfo = &(cmsg->contentInfo); cinfo != NULL; cinfo = SecCmsContentInfoGetChildContentInfo(cinfo))
{
switch (SecCmsContentInfoGetContentTypeTag(cinfo)) {
case SEC_OID_PKCS7_ENVELOPED_DATA:
case SEC_OID_PKCS7_ENCRYPTED_DATA:
return PR_TRUE;
default:
break;
}
}
return PR_FALSE;
}
Boolean
SecCmsMessageIsSigned(SecCmsMessageRef cmsg)
{
SecCmsContentInfoRef cinfo;
for (cinfo = &(cmsg->contentInfo); cinfo != NULL; cinfo = SecCmsContentInfoGetChildContentInfo(cinfo))
{
switch (SecCmsContentInfoGetContentTypeTag(cinfo)) {
case SEC_OID_PKCS7_SIGNED_DATA:
if (!SecCmsArrayIsEmpty((void **)cinfo->content.signedData->signerInfos))
return PR_TRUE;
break;
default:
break;
}
}
return PR_FALSE;
}
Boolean
SecCmsMessageIsContentEmpty(SecCmsMessageRef cmsg, unsigned int minLen)
{
CSSM_DATA_PTR item = NULL;
if (cmsg == NULL)
return PR_TRUE;
item = SecCmsContentInfoGetContent(SecCmsMessageGetContentInfo(cmsg));
if (!item) {
return PR_TRUE;
} else if(item->Length <= minLen) {
return PR_TRUE;
}
return PR_FALSE;
}
Boolean
SecCmsMessageContainsTSTInfo(SecCmsMessageRef cmsg)
{
SecCmsContentInfoRef cinfo;
for (cinfo = &(cmsg->contentInfo); cinfo != NULL; cinfo = SecCmsContentInfoGetChildContentInfo(cinfo))
{
switch (SecCmsContentInfoGetContentTypeTag(cinfo))
{
case SEC_OID_PKCS9_ID_CT_TSTInfo:
return PR_TRUE;
default:
break;
}
}
return PR_FALSE;
}
void
SecCmsMessageSetTSACallback(SecCmsMessageRef cmsg, SecCmsTSACallback tsaCallback)
{
if (cmsg)
cmsg->tsaCallback = tsaCallback;
}
void
SecCmsMessageSetTSAContext(SecCmsMessageRef cmsg, const void *tsaContext) {
if (cmsg)
cmsg->tsaContext = tsaContext;
}