michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * PKCS7 implementation -- the exported parts that are used whether michael@0: * creating or decoding. michael@0: */ michael@0: michael@0: #include "p7local.h" michael@0: michael@0: #include "cert.h" michael@0: #include "secitem.h" michael@0: #include "secoid.h" michael@0: #include "pk11func.h" michael@0: michael@0: /* michael@0: * Find out (saving pointer to lookup result for future reference) michael@0: * and return the inner content type. michael@0: */ michael@0: SECOidTag michael@0: SEC_PKCS7ContentType (SEC_PKCS7ContentInfo *cinfo) michael@0: { michael@0: if (cinfo->contentTypeTag == NULL) michael@0: cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType)); michael@0: michael@0: if (cinfo->contentTypeTag == NULL) michael@0: return SEC_OID_UNKNOWN; michael@0: michael@0: return cinfo->contentTypeTag->offset; michael@0: } michael@0: michael@0: michael@0: /* michael@0: * Destroy a PKCS7 contentInfo and all of its sub-pieces. michael@0: */ michael@0: void michael@0: SEC_PKCS7DestroyContentInfo(SEC_PKCS7ContentInfo *cinfo) michael@0: { michael@0: SECOidTag kind; michael@0: CERTCertificate **certs; michael@0: CERTCertificateList **certlists; michael@0: SEC_PKCS7SignerInfo **signerinfos; michael@0: SEC_PKCS7RecipientInfo **recipientinfos; michael@0: michael@0: PORT_Assert (cinfo->refCount > 0); michael@0: if (cinfo->refCount <= 0) michael@0: return; michael@0: michael@0: cinfo->refCount--; michael@0: if (cinfo->refCount > 0) michael@0: return; michael@0: michael@0: certs = NULL; michael@0: certlists = NULL; michael@0: recipientinfos = NULL; michael@0: signerinfos = NULL; michael@0: michael@0: kind = SEC_PKCS7ContentType (cinfo); michael@0: switch (kind) { michael@0: case SEC_OID_PKCS7_ENVELOPED_DATA: michael@0: { michael@0: SEC_PKCS7EnvelopedData *edp; michael@0: michael@0: edp = cinfo->content.envelopedData; michael@0: if (edp != NULL) { michael@0: recipientinfos = edp->recipientInfos; michael@0: } michael@0: } michael@0: break; michael@0: case SEC_OID_PKCS7_SIGNED_DATA: michael@0: { michael@0: SEC_PKCS7SignedData *sdp; michael@0: michael@0: sdp = cinfo->content.signedData; michael@0: if (sdp != NULL) { michael@0: certs = sdp->certs; michael@0: certlists = sdp->certLists; michael@0: signerinfos = sdp->signerInfos; michael@0: } michael@0: } michael@0: break; michael@0: case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: michael@0: { michael@0: SEC_PKCS7SignedAndEnvelopedData *saedp; michael@0: michael@0: saedp = cinfo->content.signedAndEnvelopedData; michael@0: if (saedp != NULL) { michael@0: certs = saedp->certs; michael@0: certlists = saedp->certLists; michael@0: recipientinfos = saedp->recipientInfos; michael@0: signerinfos = saedp->signerInfos; michael@0: if (saedp->sigKey != NULL) michael@0: PK11_FreeSymKey (saedp->sigKey); michael@0: } michael@0: } michael@0: break; michael@0: default: michael@0: /* XXX Anything else that needs to be "manually" freed/destroyed? */ michael@0: break; michael@0: } michael@0: michael@0: if (certs != NULL) { michael@0: CERTCertificate *cert; michael@0: michael@0: while ((cert = *certs++) != NULL) { michael@0: CERT_DestroyCertificate (cert); michael@0: } michael@0: } michael@0: michael@0: if (certlists != NULL) { michael@0: CERTCertificateList *certlist; michael@0: michael@0: while ((certlist = *certlists++) != NULL) { michael@0: CERT_DestroyCertificateList (certlist); michael@0: } michael@0: } michael@0: michael@0: if (recipientinfos != NULL) { michael@0: SEC_PKCS7RecipientInfo *ri; michael@0: michael@0: while ((ri = *recipientinfos++) != NULL) { michael@0: if (ri->cert != NULL) michael@0: CERT_DestroyCertificate (ri->cert); michael@0: } michael@0: } michael@0: michael@0: if (signerinfos != NULL) { michael@0: SEC_PKCS7SignerInfo *si; michael@0: michael@0: while ((si = *signerinfos++) != NULL) { michael@0: if (si->cert != NULL) michael@0: CERT_DestroyCertificate (si->cert); michael@0: if (si->certList != NULL) michael@0: CERT_DestroyCertificateList (si->certList); michael@0: } michael@0: } michael@0: michael@0: if (cinfo->poolp != NULL) { michael@0: PORT_FreeArena (cinfo->poolp, PR_FALSE); /* XXX clear it? */ michael@0: } michael@0: } michael@0: michael@0: michael@0: /* michael@0: * Return a copy of the given contentInfo. The copy may be virtual michael@0: * or may be real -- either way, the result needs to be passed to michael@0: * SEC_PKCS7DestroyContentInfo later (as does the original). michael@0: */ michael@0: SEC_PKCS7ContentInfo * michael@0: SEC_PKCS7CopyContentInfo(SEC_PKCS7ContentInfo *cinfo) michael@0: { michael@0: if (cinfo == NULL) michael@0: return NULL; michael@0: michael@0: PORT_Assert (cinfo->refCount > 0); michael@0: michael@0: if (cinfo->created) { michael@0: /* michael@0: * Want to do a real copy of these; otherwise subsequent michael@0: * changes made to either copy are likely to be a surprise. michael@0: * XXX I suspect that this will not actually be called for yet, michael@0: * which is why the assert, so to notice if it is... michael@0: */ michael@0: PORT_Assert (0); michael@0: /* michael@0: * XXX Create a new pool here, and copy everything from michael@0: * within. For cert stuff, need to call the appropriate michael@0: * copy functions, etc. michael@0: */ michael@0: } michael@0: michael@0: cinfo->refCount++; michael@0: return cinfo; michael@0: } michael@0: michael@0: michael@0: /* michael@0: * Return a pointer to the actual content. In the case of those types michael@0: * which are encrypted, this returns the *plain* content. michael@0: * XXX Needs revisiting if/when we handle nested encrypted types. michael@0: */ michael@0: SECItem * michael@0: SEC_PKCS7GetContent(SEC_PKCS7ContentInfo *cinfo) michael@0: { michael@0: SECOidTag kind; michael@0: michael@0: kind = SEC_PKCS7ContentType (cinfo); michael@0: switch (kind) { michael@0: case SEC_OID_PKCS7_DATA: michael@0: return cinfo->content.data; michael@0: case SEC_OID_PKCS7_DIGESTED_DATA: michael@0: { michael@0: SEC_PKCS7DigestedData *digd; michael@0: michael@0: digd = cinfo->content.digestedData; michael@0: if (digd == NULL) michael@0: break; michael@0: return SEC_PKCS7GetContent (&(digd->contentInfo)); michael@0: } michael@0: case SEC_OID_PKCS7_ENCRYPTED_DATA: michael@0: { michael@0: SEC_PKCS7EncryptedData *encd; michael@0: michael@0: encd = cinfo->content.encryptedData; michael@0: if (encd == NULL) michael@0: break; michael@0: return &(encd->encContentInfo.plainContent); michael@0: } michael@0: case SEC_OID_PKCS7_ENVELOPED_DATA: michael@0: { michael@0: SEC_PKCS7EnvelopedData *envd; michael@0: michael@0: envd = cinfo->content.envelopedData; michael@0: if (envd == NULL) michael@0: break; michael@0: return &(envd->encContentInfo.plainContent); michael@0: } michael@0: case SEC_OID_PKCS7_SIGNED_DATA: michael@0: { michael@0: SEC_PKCS7SignedData *sigd; michael@0: michael@0: sigd = cinfo->content.signedData; michael@0: if (sigd == NULL) michael@0: break; michael@0: return SEC_PKCS7GetContent (&(sigd->contentInfo)); michael@0: } michael@0: case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: michael@0: { michael@0: SEC_PKCS7SignedAndEnvelopedData *saed; michael@0: michael@0: saed = cinfo->content.signedAndEnvelopedData; michael@0: if (saed == NULL) michael@0: break; michael@0: return &(saed->encContentInfo.plainContent); michael@0: } michael@0: default: michael@0: PORT_Assert(0); michael@0: break; michael@0: } michael@0: michael@0: return NULL; michael@0: } michael@0: michael@0: michael@0: /* michael@0: * XXX Fix the placement and formatting of the michael@0: * following routines (i.e. make them consistent with the rest of michael@0: * the pkcs7 code -- I think some/many belong in other files and michael@0: * they all need a formatting/style rehaul) michael@0: */ michael@0: michael@0: /* retrieve the algorithm identifier for encrypted data. michael@0: * the identifier returned is a copy of the algorithm identifier michael@0: * in the content info and needs to be freed after being used. michael@0: * michael@0: * cinfo is the content info for which to retrieve the michael@0: * encryption algorithm. michael@0: * michael@0: * if the content info is not encrypted data or an error michael@0: * occurs NULL is returned. michael@0: */ michael@0: SECAlgorithmID * michael@0: SEC_PKCS7GetEncryptionAlgorithm(SEC_PKCS7ContentInfo *cinfo) michael@0: { michael@0: SECAlgorithmID *alg = 0; michael@0: switch (SEC_PKCS7ContentType(cinfo)) michael@0: { michael@0: case SEC_OID_PKCS7_ENCRYPTED_DATA: michael@0: alg = &cinfo->content.encryptedData->encContentInfo.contentEncAlg; michael@0: break; michael@0: case SEC_OID_PKCS7_ENVELOPED_DATA: michael@0: alg = &cinfo->content.envelopedData->encContentInfo.contentEncAlg; michael@0: break; michael@0: case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: michael@0: alg = &cinfo->content.signedAndEnvelopedData michael@0: ->encContentInfo.contentEncAlg; michael@0: break; michael@0: default: michael@0: alg = 0; michael@0: break; michael@0: } michael@0: michael@0: return alg; michael@0: } michael@0: michael@0: /* set the content of the content info. For data content infos, michael@0: * the data is set. For encrytped content infos, the plainContent michael@0: * is set, and is expected to be encrypted later. michael@0: * michael@0: * cinfo is the content info where the data will be set michael@0: * michael@0: * buf is a buffer of the data to set michael@0: * michael@0: * len is the length of the data being set. michael@0: * michael@0: * in the event of an error, SECFailure is returned. SECSuccess michael@0: * indicates the content was successfully set. michael@0: */ michael@0: SECStatus michael@0: SEC_PKCS7SetContent(SEC_PKCS7ContentInfo *cinfo, michael@0: const char *buf, michael@0: unsigned long len) michael@0: { michael@0: SECOidTag cinfo_type; michael@0: SECStatus rv; michael@0: SECItem content; michael@0: SECOidData *contentTypeTag = NULL; michael@0: michael@0: content.type = siBuffer; michael@0: content.data = (unsigned char *)buf; michael@0: content.len = len; michael@0: michael@0: cinfo_type = SEC_PKCS7ContentType(cinfo); michael@0: michael@0: /* set inner content */ michael@0: switch(cinfo_type) michael@0: { michael@0: case SEC_OID_PKCS7_SIGNED_DATA: michael@0: if(content.len > 0) { michael@0: /* we "leak" the old content here, but as it's all in the pool */ michael@0: /* it does not really matter */ michael@0: michael@0: /* create content item if necessary */ michael@0: if (cinfo->content.signedData->contentInfo.content.data == NULL) michael@0: cinfo->content.signedData->contentInfo.content.data = SECITEM_AllocItem(cinfo->poolp, NULL, 0); michael@0: rv = SECITEM_CopyItem(cinfo->poolp, michael@0: cinfo->content.signedData->contentInfo.content.data, michael@0: &content); michael@0: } else { michael@0: cinfo->content.signedData->contentInfo.content.data->data = NULL; michael@0: cinfo->content.signedData->contentInfo.content.data->len = 0; michael@0: rv = SECSuccess; michael@0: } michael@0: if(rv == SECFailure) michael@0: goto loser; michael@0: michael@0: break; michael@0: case SEC_OID_PKCS7_ENCRYPTED_DATA: michael@0: /* XXX this forces the inner content type to be "data" */ michael@0: /* do we really want to override without asking or reason? */ michael@0: contentTypeTag = SECOID_FindOIDByTag(SEC_OID_PKCS7_DATA); michael@0: if(contentTypeTag == NULL) michael@0: goto loser; michael@0: rv = SECITEM_CopyItem(cinfo->poolp, michael@0: &(cinfo->content.encryptedData->encContentInfo.contentType), michael@0: &(contentTypeTag->oid)); michael@0: if(rv == SECFailure) michael@0: goto loser; michael@0: if(content.len > 0) { michael@0: rv = SECITEM_CopyItem(cinfo->poolp, michael@0: &(cinfo->content.encryptedData->encContentInfo.plainContent), michael@0: &content); michael@0: } else { michael@0: cinfo->content.encryptedData->encContentInfo.plainContent.data = NULL; michael@0: cinfo->content.encryptedData->encContentInfo.encContent.data = NULL; michael@0: cinfo->content.encryptedData->encContentInfo.plainContent.len = 0; michael@0: cinfo->content.encryptedData->encContentInfo.encContent.len = 0; michael@0: rv = SECSuccess; michael@0: } michael@0: if(rv == SECFailure) michael@0: goto loser; michael@0: break; michael@0: case SEC_OID_PKCS7_DATA: michael@0: cinfo->content.data = (SECItem *)PORT_ArenaZAlloc(cinfo->poolp, michael@0: sizeof(SECItem)); michael@0: if(cinfo->content.data == NULL) michael@0: goto loser; michael@0: if(content.len > 0) { michael@0: rv = SECITEM_CopyItem(cinfo->poolp, michael@0: cinfo->content.data, &content); michael@0: } else { michael@0: /* handle case with NULL content */ michael@0: rv = SECSuccess; michael@0: } michael@0: if(rv == SECFailure) michael@0: goto loser; michael@0: break; michael@0: default: michael@0: goto loser; michael@0: } michael@0: michael@0: return SECSuccess; michael@0: michael@0: loser: michael@0: michael@0: return SECFailure; michael@0: } michael@0: michael@0: /* the content of an encrypted data content info is encrypted. michael@0: * it is assumed that for encrypted data, that the data has already michael@0: * been set and is in the "plainContent" field of the content info. michael@0: * michael@0: * cinfo is the content info to encrypt michael@0: * michael@0: * key is the key with which to perform the encryption. if the michael@0: * algorithm is a password based encryption algorithm, the michael@0: * key is actually a password which will be processed per michael@0: * PKCS #5. michael@0: * michael@0: * in the event of an error, SECFailure is returned. SECSuccess michael@0: * indicates a success. michael@0: */ michael@0: SECStatus michael@0: SEC_PKCS7EncryptContents(PLArenaPool *poolp, michael@0: SEC_PKCS7ContentInfo *cinfo, michael@0: SECItem *key, michael@0: void *wincx) michael@0: { michael@0: SECAlgorithmID *algid = NULL; michael@0: SECItem * result = NULL; michael@0: SECItem * src; michael@0: SECItem * dest; michael@0: SECItem * blocked_data = NULL; michael@0: void * mark; michael@0: void * cx; michael@0: PK11SymKey * eKey = NULL; michael@0: PK11SlotInfo * slot = NULL; michael@0: michael@0: CK_MECHANISM_TYPE cryptoMechType; michael@0: int bs; michael@0: SECStatus rv = SECFailure; michael@0: SECItem *c_param = NULL; michael@0: michael@0: if((cinfo == NULL) || (key == NULL)) michael@0: return SECFailure; michael@0: michael@0: if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA) michael@0: return SECFailure; michael@0: michael@0: algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo); michael@0: if(algid == NULL) michael@0: return SECFailure; michael@0: michael@0: if(poolp == NULL) michael@0: poolp = cinfo->poolp; michael@0: michael@0: mark = PORT_ArenaMark(poolp); michael@0: michael@0: src = &cinfo->content.encryptedData->encContentInfo.plainContent; michael@0: dest = &cinfo->content.encryptedData->encContentInfo.encContent; michael@0: dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64)); michael@0: dest->len = (src->len + 64); michael@0: if(dest->data == NULL) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: michael@0: slot = PK11_GetInternalKeySlot(); michael@0: if(slot == NULL) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: michael@0: eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx); michael@0: if(eKey == NULL) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: michael@0: cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key); michael@0: if (cryptoMechType == CKM_INVALID_MECHANISM) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: michael@0: /* block according to PKCS 8 */ michael@0: bs = PK11_GetBlockSize(cryptoMechType, c_param); michael@0: rv = SECSuccess; michael@0: if(bs) { michael@0: char pad_char; michael@0: pad_char = (char)(bs - (src->len % bs)); michael@0: if(src->len % bs) { michael@0: rv = SECSuccess; michael@0: blocked_data = PK11_BlockData(src, bs); michael@0: if(blocked_data) { michael@0: PORT_Memset((blocked_data->data + blocked_data->len michael@0: - (int)pad_char), michael@0: pad_char, (int)pad_char); michael@0: } else { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: } else { michael@0: blocked_data = SECITEM_DupItem(src); michael@0: if(blocked_data) { michael@0: blocked_data->data = (unsigned char*)PORT_Realloc( michael@0: blocked_data->data, michael@0: blocked_data->len + bs); michael@0: if(blocked_data->data) { michael@0: blocked_data->len += bs; michael@0: PORT_Memset((blocked_data->data + src->len), (char)bs, bs); michael@0: } else { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: } else { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: } michael@0: } else { michael@0: blocked_data = SECITEM_DupItem(src); michael@0: if(!blocked_data) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: } michael@0: michael@0: cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT, michael@0: eKey, c_param); michael@0: if(cx == NULL) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: michael@0: rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len), michael@0: (int)(src->len + 64), blocked_data->data, michael@0: (int)blocked_data->len); michael@0: PK11_DestroyContext((PK11Context*)cx, PR_TRUE); michael@0: michael@0: loser: michael@0: /* let success fall through */ michael@0: if(blocked_data != NULL) michael@0: SECITEM_ZfreeItem(blocked_data, PR_TRUE); michael@0: michael@0: if(result != NULL) michael@0: SECITEM_ZfreeItem(result, PR_TRUE); michael@0: michael@0: if(rv == SECFailure) michael@0: PORT_ArenaRelease(poolp, mark); michael@0: else michael@0: PORT_ArenaUnmark(poolp, mark); michael@0: michael@0: if(eKey != NULL) michael@0: PK11_FreeSymKey(eKey); michael@0: michael@0: if(slot != NULL) michael@0: PK11_FreeSlot(slot); michael@0: michael@0: if(c_param != NULL) michael@0: SECITEM_ZfreeItem(c_param, PR_TRUE); michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: /* the content of an encrypted data content info is decrypted. michael@0: * it is assumed that for encrypted data, that the data has already michael@0: * been set and is in the "encContent" field of the content info. michael@0: * michael@0: * cinfo is the content info to decrypt michael@0: * michael@0: * key is the key with which to perform the decryption. if the michael@0: * algorithm is a password based encryption algorithm, the michael@0: * key is actually a password which will be processed per michael@0: * PKCS #5. michael@0: * michael@0: * in the event of an error, SECFailure is returned. SECSuccess michael@0: * indicates a success. michael@0: */ michael@0: SECStatus michael@0: SEC_PKCS7DecryptContents(PLArenaPool *poolp, michael@0: SEC_PKCS7ContentInfo *cinfo, michael@0: SECItem *key, michael@0: void *wincx) michael@0: { michael@0: SECAlgorithmID *algid = NULL; michael@0: SECStatus rv = SECFailure; michael@0: SECItem *result = NULL, *dest, *src; michael@0: void *mark; michael@0: michael@0: PK11SymKey *eKey = NULL; michael@0: PK11SlotInfo *slot = NULL; michael@0: CK_MECHANISM_TYPE cryptoMechType; michael@0: void *cx; michael@0: SECItem *c_param = NULL; michael@0: int bs; michael@0: michael@0: if((cinfo == NULL) || (key == NULL)) michael@0: return SECFailure; michael@0: michael@0: if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA) michael@0: return SECFailure; michael@0: michael@0: algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo); michael@0: if(algid == NULL) michael@0: return SECFailure; michael@0: michael@0: if(poolp == NULL) michael@0: poolp = cinfo->poolp; michael@0: michael@0: mark = PORT_ArenaMark(poolp); michael@0: michael@0: src = &cinfo->content.encryptedData->encContentInfo.encContent; michael@0: dest = &cinfo->content.encryptedData->encContentInfo.plainContent; michael@0: dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64)); michael@0: dest->len = (src->len + 64); michael@0: if(dest->data == NULL) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: michael@0: slot = PK11_GetInternalKeySlot(); michael@0: if(slot == NULL) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: michael@0: eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx); michael@0: if(eKey == NULL) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: michael@0: cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key); michael@0: if (cryptoMechType == CKM_INVALID_MECHANISM) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: michael@0: cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT, michael@0: eKey, c_param); michael@0: if(cx == NULL) { michael@0: rv = SECFailure; michael@0: goto loser; michael@0: } michael@0: michael@0: rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len), michael@0: (int)(src->len + 64), src->data, (int)src->len); michael@0: PK11_DestroyContext((PK11Context *)cx, PR_TRUE); michael@0: michael@0: bs = PK11_GetBlockSize(cryptoMechType, c_param); michael@0: if(bs) { michael@0: /* check for proper badding in block algorithms. this assumes michael@0: * RC2 cbc or a DES cbc variant. and the padding is thus defined michael@0: */ michael@0: if(((int)dest->data[dest->len-1] <= bs) && michael@0: ((int)dest->data[dest->len-1] > 0)) { michael@0: dest->len -= (int)dest->data[dest->len-1]; michael@0: } else { michael@0: rv = SECFailure; michael@0: /* set an error ? */ michael@0: } michael@0: } michael@0: michael@0: loser: michael@0: /* let success fall through */ michael@0: if(result != NULL) michael@0: SECITEM_ZfreeItem(result, PR_TRUE); michael@0: michael@0: if(rv == SECFailure) michael@0: PORT_ArenaRelease(poolp, mark); michael@0: else michael@0: PORT_ArenaUnmark(poolp, mark); michael@0: michael@0: if(eKey != NULL) michael@0: PK11_FreeSymKey(eKey); michael@0: michael@0: if(slot != NULL) michael@0: PK11_FreeSlot(slot); michael@0: michael@0: if(c_param != NULL) michael@0: SECITEM_ZfreeItem(c_param, PR_TRUE); michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: SECItem ** michael@0: SEC_PKCS7GetCertificateList(SEC_PKCS7ContentInfo *cinfo) michael@0: { michael@0: switch(SEC_PKCS7ContentType(cinfo)) michael@0: { michael@0: case SEC_OID_PKCS7_SIGNED_DATA: michael@0: return cinfo->content.signedData->rawCerts; michael@0: break; michael@0: default: michael@0: return NULL; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: michael@0: int michael@0: SEC_PKCS7GetKeyLength(SEC_PKCS7ContentInfo *cinfo) michael@0: { michael@0: if (cinfo->contentTypeTag->offset == SEC_OID_PKCS7_ENVELOPED_DATA) michael@0: return cinfo->content.envelopedData->encContentInfo.keysize; michael@0: else michael@0: return 0; michael@0: } michael@0: