#include <Security/SecCmsEncoder.h>
#include <Security/SecCmsSignerInfo.h>
#include "cmslocal.h"
#include "SecAsn1Item.h"
#include "secoid.h"
#include "cryptohi.h"
#include <security_asn1/secasn1.h>
#include <security_asn1/secerr.h>
#include <security_asn1/secport.h>
#if USE_CDSA_CRYPTO
#include <Security/cssmapi.h>
#include <Security/cssmapple.h>
#include <Security/SecBase.h>
#else
#include <CommonCrypto/CommonDigest.h>
#include <Security/SecBase.h>
#endif
OSStatus
SecCmsArraySortByDER(void **objs, const SecAsn1Template *objtemplate, void **objs2)
{
PRArenaPool *poolp;
int num_objs;
SecAsn1Item **enc_objs;
OSStatus rv = SECFailure;
int i;
if (objs == NULL)
return SECSuccess;
num_objs = SecCmsArrayCount((void **)objs);
if (num_objs == 0 || num_objs == 1)
return SECSuccess;
poolp = PORT_NewArena (1024);
if (poolp == NULL)
return SECFailure;
if (num_objs<0 || num_objs>=(int)((INT_MAX/sizeof(SecAsn1Item *))-1)) {
goto loser;
}
enc_objs = (SecAsn1Item **)PORT_ArenaZAlloc(poolp, (num_objs + 1) * sizeof(SecAsn1Item *));
if (enc_objs == NULL)
goto loser;
for (i = 0; i < num_objs; i++) {
enc_objs[i] = SEC_ASN1EncodeItem(poolp, NULL, objs[i], objtemplate);
if (enc_objs[i] == NULL)
goto loser;
}
enc_objs[num_objs] = NULL;
SecCmsArraySort((void **)enc_objs, SecCmsUtilDERCompare, objs, objs2);
rv = SECSuccess;
loser:
PORT_FreeArena (poolp, PR_FALSE);
return rv;
}
int
SecCmsUtilDERCompare(void *a, void *b)
{
SecAsn1Item * der1 = (SecAsn1Item *)a;
SecAsn1Item * der2 = (SecAsn1Item *)b;
if (der1->Length != der2->Length)
return (der1->Length < der2->Length) ? -1 : 1;
#if 1
return memcmp(der1->Data, der2->Data, der1->Length);
#else
size_t j;
for (j = 0; j < der1->Length; j++) {
if (der1->Data[j] == der2->Data[j])
continue;
return (der1->Data[j] < der2->Data[j]) ? -1 : 1;
}
return 0;
#endif
}
int
SecCmsAlgArrayGetIndexByAlgID(SECAlgorithmID **algorithmArray, SECAlgorithmID *algid)
{
int i;
if (algorithmArray == NULL || algorithmArray[0] == NULL)
return -1;
for (i = 0; algorithmArray[i] != NULL; i++) {
if (SECOID_CompareAlgorithmID(algorithmArray[i], algid) == SECEqual)
break;
}
if (algorithmArray[i] == NULL)
return -1;
return i;
}
int
SecCmsAlgArrayGetIndexByAlgTag(SECAlgorithmID **algorithmArray,
SECOidTag algtag)
{
SECOidData *algid;
int i = -1;
if (algorithmArray == NULL || algorithmArray[0] == NULL)
return i;
#ifdef ORDER_N_SQUARED
for (i = 0; algorithmArray[i] != NULL; i++) {
algid = SECOID_FindOID(&(algorithmArray[i]->algorithm));
if (algid->offset == algtag)
break;
}
#else
algid = SECOID_FindOIDByTag(algtag);
if (!algid)
return i;
for (i = 0; algorithmArray[i] != NULL; i++) {
if (SECITEM_ItemsAreEqual(&algorithmArray[i]->algorithm, &algid->oid))
break;
}
#endif
if (algorithmArray[i] == NULL)
return -1;
return i;
}
void *
SecCmsUtilGetHashObjByAlgID(SECAlgorithmID *algid)
{
SECOidData *oidData = SECOID_FindOID(&(algid->algorithm));
if (oidData)
{
void *digobj = NULL;
switch (oidData->offset) {
case SEC_OID_SHA1:
digobj = calloc(1, sizeof(CC_SHA1_CTX));
CC_SHA1_Init(digobj);
break;
case SEC_OID_MD5:
digobj = calloc(1, sizeof(CC_MD5_CTX));
CC_MD5_Init(digobj);
break;
case SEC_OID_SHA224:
digobj = calloc(1, sizeof(CC_SHA256_CTX));
CC_SHA224_Init(digobj);
break;
case SEC_OID_SHA256:
digobj = calloc(1, sizeof(CC_SHA256_CTX));
CC_SHA256_Init(digobj);
break;
case SEC_OID_SHA384:
digobj = calloc(1, sizeof(CC_SHA512_CTX));
CC_SHA384_Init(digobj);
break;
case SEC_OID_SHA512:
digobj = calloc(1, sizeof(CC_SHA512_CTX));
CC_SHA512_Init(digobj);
break;
default:
break;
}
return digobj;
}
return 0;
}
SECOidTag
SecCmsUtilMakeSignatureAlgorithm(SECOidTag hashalg, SECOidTag encalg)
{
switch (encalg) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
switch (hashalg) {
case SEC_OID_MD2:
return SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
case SEC_OID_MD5:
return SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA1:
return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA256:
return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA384:
return SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA512:
return SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
default:
return SEC_OID_UNKNOWN;
}
case SEC_OID_ANSIX9_DSA_SIGNATURE:
case SEC_OID_MISSI_KEA_DSS:
case SEC_OID_MISSI_DSS:
switch (hashalg) {
case SEC_OID_SHA1:
return SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
default:
return SEC_OID_UNKNOWN;
}
case SEC_OID_EC_PUBLIC_KEY:
switch(hashalg) {
case SEC_OID_SHA1:
return SEC_OID_ECDSA_WithSHA1;
case SEC_OID_SHA256:
return SEC_OID_ECDSA_WITH_SHA256;
case SEC_OID_SHA384:
return SEC_OID_ECDSA_WITH_SHA384;
case SEC_OID_SHA512:
return SEC_OID_ECDSA_WITH_SHA512;
default:
return SEC_OID_UNKNOWN;
}
default:
break;
}
return encalg;
}
const SecAsn1Template *
SecCmsUtilGetTemplateByTypeTag(SECOidTag type)
{
const SecAsn1Template *template;
extern const SecAsn1Template SecCmsSignedDataTemplate[];
extern const SecAsn1Template SecCmsEnvelopedDataTemplate[];
extern const SecAsn1Template SecCmsEncryptedDataTemplate[];
extern const SecAsn1Template SecCmsDigestedDataTemplate[];
switch (type) {
case SEC_OID_PKCS7_SIGNED_DATA:
template = SecCmsSignedDataTemplate;
break;
case SEC_OID_PKCS7_ENVELOPED_DATA:
template = SecCmsEnvelopedDataTemplate;
break;
case SEC_OID_PKCS7_ENCRYPTED_DATA:
template = SecCmsEncryptedDataTemplate;
break;
case SEC_OID_PKCS7_DIGESTED_DATA:
template = SecCmsDigestedDataTemplate;
break;
default:
case SEC_OID_PKCS7_DATA:
template = NULL;
break;
}
return template;
}
size_t
SecCmsUtilGetSizeByTypeTag(SECOidTag type)
{
size_t size;
switch (type) {
case SEC_OID_PKCS7_SIGNED_DATA:
size = sizeof(SecCmsSignedData);
break;
case SEC_OID_PKCS7_ENVELOPED_DATA:
size = sizeof(SecCmsEnvelopedData);
break;
case SEC_OID_PKCS7_ENCRYPTED_DATA:
size = sizeof(SecCmsEncryptedData);
break;
case SEC_OID_PKCS7_DIGESTED_DATA:
size = sizeof(SecCmsDigestedData);
break;
default:
case SEC_OID_PKCS7_DATA:
size = 0;
break;
}
return size;
}
SecCmsContentInfoRef
SecCmsContentGetContentInfo(void *msg, SECOidTag type)
{
SecCmsContent c;
SecCmsContentInfoRef cinfo;
if (!msg)
return NULL;
c.pointer = msg;
switch (type) {
case SEC_OID_PKCS7_SIGNED_DATA:
cinfo = &(c.signedData->contentInfo);
break;
case SEC_OID_PKCS7_ENVELOPED_DATA:
cinfo = &(c.envelopedData->contentInfo);
break;
case SEC_OID_PKCS7_ENCRYPTED_DATA:
cinfo = &(c.encryptedData->contentInfo);
break;
case SEC_OID_PKCS7_DIGESTED_DATA:
cinfo = &(c.digestedData->contentInfo);
break;
default:
cinfo = NULL;
}
return cinfo;
}
const char *
SecCmsUtilVerificationStatusToString(SecCmsVerificationStatus vs)
{
switch (vs) {
case SecCmsVSUnverified: return "Unverified";
case SecCmsVSGoodSignature: return "GoodSignature";
case SecCmsVSBadSignature: return "BadSignature";
case SecCmsVSDigestMismatch: return "DigestMismatch";
case SecCmsVSSigningCertNotFound: return "SigningCertNotFound";
case SecCmsVSSigningCertNotTrusted: return "SigningCertNotTrusted";
case SecCmsVSSignatureAlgorithmUnknown: return "SignatureAlgorithmUnknown";
case SecCmsVSSignatureAlgorithmUnsupported: return "SignatureAlgorithmUnsupported";
case SecCmsVSMalformedSignature: return "MalformedSignature";
case SecCmsVSProcessingError: return "ProcessingError";
default: return "Unknown";
}
}