Back to index

lightning-sunbird  0.9+nobinonly
p7common.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038  * PKCS7 implementation -- the exported parts that are used whether
00039  * creating or decoding.
00040  *
00041  * $Id: p7common.c,v 1.4 2004/04/25 15:03:13 gerv%gerv.net Exp $
00042  */
00043 
00044 #include "p7local.h"
00045 
00046 #include "cert.h"
00047 #include "secitem.h"
00048 #include "secoid.h"
00049 #include "pk11func.h"
00050 
00051 /*
00052  * Find out (saving pointer to lookup result for future reference)
00053  * and return the inner content type.
00054  */
00055 SECOidTag
00056 SEC_PKCS7ContentType (SEC_PKCS7ContentInfo *cinfo)
00057 {
00058     if (cinfo->contentTypeTag == NULL)
00059        cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
00060 
00061     if (cinfo->contentTypeTag == NULL)
00062        return SEC_OID_UNKNOWN;
00063 
00064     return cinfo->contentTypeTag->offset;
00065 }
00066 
00067 
00068 /*
00069  * Destroy a PKCS7 contentInfo and all of its sub-pieces.
00070  */
00071 void
00072 SEC_PKCS7DestroyContentInfo(SEC_PKCS7ContentInfo *cinfo)
00073 {
00074     SECOidTag kind;
00075     CERTCertificate **certs;
00076     CERTCertificateList **certlists;
00077     SEC_PKCS7SignerInfo **signerinfos;
00078     SEC_PKCS7RecipientInfo **recipientinfos;
00079 
00080     PORT_Assert (cinfo->refCount > 0);
00081     if (cinfo->refCount <= 0)
00082        return;
00083 
00084     cinfo->refCount--;
00085     if (cinfo->refCount > 0)
00086        return;
00087 
00088     certs = NULL;
00089     certlists = NULL;
00090     recipientinfos = NULL;
00091     signerinfos = NULL;
00092 
00093     kind = SEC_PKCS7ContentType (cinfo);
00094     switch (kind) {
00095       case SEC_OID_PKCS7_ENVELOPED_DATA:
00096        {
00097            SEC_PKCS7EnvelopedData *edp;
00098 
00099            edp = cinfo->content.envelopedData;
00100            if (edp != NULL) {
00101               recipientinfos = edp->recipientInfos;
00102            }
00103        }
00104        break;
00105       case SEC_OID_PKCS7_SIGNED_DATA:
00106        {
00107            SEC_PKCS7SignedData *sdp;
00108 
00109            sdp = cinfo->content.signedData;
00110            if (sdp != NULL) {
00111               certs = sdp->certs;
00112               certlists = sdp->certLists;
00113               signerinfos = sdp->signerInfos;
00114            }
00115        }
00116        break;
00117       case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
00118        {
00119            SEC_PKCS7SignedAndEnvelopedData *saedp;
00120 
00121            saedp = cinfo->content.signedAndEnvelopedData;
00122            if (saedp != NULL) {
00123               certs = saedp->certs;
00124               certlists = saedp->certLists;
00125               recipientinfos = saedp->recipientInfos;
00126               signerinfos = saedp->signerInfos;
00127               if (saedp->sigKey != NULL)
00128                   PK11_FreeSymKey (saedp->sigKey);
00129            }
00130        }
00131        break;
00132       default:
00133        /* XXX Anything else that needs to be "manually" freed/destroyed? */
00134        break;
00135     }
00136 
00137     if (certs != NULL) {
00138        CERTCertificate *cert;
00139 
00140        while ((cert = *certs++) != NULL) {
00141            CERT_DestroyCertificate (cert);
00142        }
00143     }
00144 
00145     if (certlists != NULL) {
00146        CERTCertificateList *certlist;
00147 
00148        while ((certlist = *certlists++) != NULL) {
00149            CERT_DestroyCertificateList (certlist);
00150        }
00151     }
00152 
00153     if (recipientinfos != NULL) {
00154        SEC_PKCS7RecipientInfo *ri;
00155 
00156        while ((ri = *recipientinfos++) != NULL) {
00157            if (ri->cert != NULL)
00158               CERT_DestroyCertificate (ri->cert);
00159        }
00160     }
00161 
00162     if (signerinfos != NULL) {
00163        SEC_PKCS7SignerInfo *si;
00164 
00165        while ((si = *signerinfos++) != NULL) {
00166            if (si->cert != NULL)
00167               CERT_DestroyCertificate (si->cert);
00168            if (si->certList != NULL)
00169               CERT_DestroyCertificateList (si->certList);
00170        }
00171     }
00172 
00173     if (cinfo->poolp != NULL) {
00174        PORT_FreeArena (cinfo->poolp, PR_FALSE);  /* XXX clear it? */
00175     }
00176 }
00177 
00178 
00179 /*
00180  * Return a copy of the given contentInfo.  The copy may be virtual
00181  * or may be real -- either way, the result needs to be passed to
00182  * SEC_PKCS7DestroyContentInfo later (as does the original).
00183  */
00184 SEC_PKCS7ContentInfo *
00185 SEC_PKCS7CopyContentInfo(SEC_PKCS7ContentInfo *cinfo)
00186 {
00187     if (cinfo == NULL)
00188        return NULL;
00189 
00190     PORT_Assert (cinfo->refCount > 0);
00191 
00192     if (cinfo->created) {
00193        /*
00194         * Want to do a real copy of these; otherwise subsequent
00195         * changes made to either copy are likely to be a surprise.
00196         * XXX I suspect that this will not actually be called for yet,
00197         * which is why the assert, so to notice if it is...
00198         */
00199        PORT_Assert (0);
00200        /*
00201         * XXX Create a new pool here, and copy everything from
00202         * within.  For cert stuff, need to call the appropriate
00203         * copy functions, etc.
00204         */
00205     }
00206 
00207     cinfo->refCount++;
00208     return cinfo;
00209 }
00210 
00211 
00212 /*
00213  * Return a pointer to the actual content.  In the case of those types
00214  * which are encrypted, this returns the *plain* content.
00215  * XXX Needs revisiting if/when we handle nested encrypted types.
00216  */
00217 SECItem *
00218 SEC_PKCS7GetContent(SEC_PKCS7ContentInfo *cinfo)
00219 {
00220     SECOidTag kind;
00221 
00222     kind = SEC_PKCS7ContentType (cinfo);
00223     switch (kind) {
00224       case SEC_OID_PKCS7_DATA:
00225        return cinfo->content.data;
00226       case SEC_OID_PKCS7_DIGESTED_DATA:
00227        {
00228            SEC_PKCS7DigestedData *digd;
00229 
00230            digd = cinfo->content.digestedData;
00231            if (digd == NULL)
00232               break;
00233            return SEC_PKCS7GetContent (&(digd->contentInfo));
00234        }
00235       case SEC_OID_PKCS7_ENCRYPTED_DATA:
00236        {
00237            SEC_PKCS7EncryptedData *encd;
00238 
00239            encd = cinfo->content.encryptedData;
00240            if (encd == NULL)
00241               break;
00242            return &(encd->encContentInfo.plainContent);
00243        }
00244       case SEC_OID_PKCS7_ENVELOPED_DATA:
00245        {
00246            SEC_PKCS7EnvelopedData *envd;
00247 
00248            envd = cinfo->content.envelopedData;
00249            if (envd == NULL)
00250               break;
00251            return &(envd->encContentInfo.plainContent);
00252        }
00253       case SEC_OID_PKCS7_SIGNED_DATA:
00254        {
00255            SEC_PKCS7SignedData *sigd;
00256 
00257            sigd = cinfo->content.signedData;
00258            if (sigd == NULL)
00259               break;
00260            return SEC_PKCS7GetContent (&(sigd->contentInfo));
00261        }
00262       case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
00263        {
00264            SEC_PKCS7SignedAndEnvelopedData *saed;
00265 
00266            saed = cinfo->content.signedAndEnvelopedData;
00267            if (saed == NULL)
00268               break;
00269            return &(saed->encContentInfo.plainContent);
00270        }
00271       default:
00272        PORT_Assert(0);
00273        break;
00274     }
00275 
00276     return NULL;
00277 }
00278 
00279 
00280 /*
00281  * XXX Fix the placement and formatting of the
00282  * following routines (i.e. make them consistent with the rest of
00283  * the pkcs7 code -- I think some/many belong in other files and
00284  * they all need a formatting/style rehaul)
00285  */
00286 
00287 /* retrieve the algorithm identifier for encrypted data.  
00288  * the identifier returned is a copy of the algorithm identifier
00289  * in the content info and needs to be freed after being used.
00290  *
00291  *   cinfo is the content info for which to retrieve the
00292  *     encryption algorithm.
00293  *
00294  * if the content info is not encrypted data or an error 
00295  * occurs NULL is returned.
00296  */
00297 SECAlgorithmID *
00298 SEC_PKCS7GetEncryptionAlgorithm(SEC_PKCS7ContentInfo *cinfo)
00299 {
00300   SECAlgorithmID *alg = 0;
00301   switch (SEC_PKCS7ContentType(cinfo))
00302     {
00303     case SEC_OID_PKCS7_ENCRYPTED_DATA:
00304       alg = &cinfo->content.encryptedData->encContentInfo.contentEncAlg;
00305       break;
00306     case SEC_OID_PKCS7_ENVELOPED_DATA:
00307       alg = &cinfo->content.envelopedData->encContentInfo.contentEncAlg;
00308       break;
00309     case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
00310       alg = &cinfo->content.signedAndEnvelopedData
00311        ->encContentInfo.contentEncAlg;
00312       break;
00313     default:
00314       alg = 0;
00315       break;
00316     }
00317 
00318     return alg;
00319 }
00320 
00321 /* set the content of the content info.  For data content infos,
00322  * the data is set.  For encrytped content infos, the plainContent
00323  * is set, and is expected to be encrypted later.
00324  *  
00325  * cinfo is the content info where the data will be set
00326  *
00327  * buf is a buffer of the data to set
00328  *
00329  * len is the length of the data being set.
00330  *
00331  * in the event of an error, SECFailure is returned.  SECSuccess 
00332  * indicates the content was successfully set.
00333  */
00334 SECStatus 
00335 SEC_PKCS7SetContent(SEC_PKCS7ContentInfo *cinfo,
00336                   const char *buf, 
00337                   unsigned long len)
00338 {
00339     SECOidTag cinfo_type;
00340     SECStatus rv;
00341     SECItem content;
00342     SECOidData *contentTypeTag = NULL;
00343 
00344     content.data = (unsigned char *)buf;
00345     content.len = len;
00346 
00347     cinfo_type = SEC_PKCS7ContentType(cinfo);
00348 
00349     /* set inner content */
00350     switch(cinfo_type)
00351     {
00352        case SEC_OID_PKCS7_SIGNED_DATA:
00353            if(content.len > 0) {
00354               /* we "leak" the old content here, but as it's all in the pool */
00355               /* it does not really matter */
00356 
00357               /* create content item if necessary */
00358               if (cinfo->content.signedData->contentInfo.content.data == NULL)
00359                   cinfo->content.signedData->contentInfo.content.data = SECITEM_AllocItem(cinfo->poolp, NULL, 0);
00360               rv = SECITEM_CopyItem(cinfo->poolp, 
00361                      cinfo->content.signedData->contentInfo.content.data,
00362                      &content);
00363            } else {
00364               cinfo->content.signedData->contentInfo.content.data->data = NULL;
00365               cinfo->content.signedData->contentInfo.content.data->len = 0;
00366               rv = SECSuccess;
00367            }
00368            if(rv == SECFailure)
00369               goto loser;
00370            
00371            break;
00372        case SEC_OID_PKCS7_ENCRYPTED_DATA:
00373            /* XXX this forces the inner content type to be "data" */
00374            /* do we really want to override without asking or reason? */
00375            contentTypeTag = SECOID_FindOIDByTag(SEC_OID_PKCS7_DATA);
00376            if(contentTypeTag == NULL)
00377               goto loser;
00378            rv = SECITEM_CopyItem(cinfo->poolp, 
00379               &(cinfo->content.encryptedData->encContentInfo.contentType),
00380               &(contentTypeTag->oid));
00381            if(rv == SECFailure)
00382               goto loser;
00383            if(content.len > 0) {
00384               rv = SECITEM_CopyItem(cinfo->poolp, 
00385                      &(cinfo->content.encryptedData->encContentInfo.plainContent),
00386                      &content);
00387            } else {
00388               cinfo->content.encryptedData->encContentInfo.plainContent.data = NULL;
00389               cinfo->content.encryptedData->encContentInfo.encContent.data = NULL;
00390               cinfo->content.encryptedData->encContentInfo.plainContent.len = 0;
00391               cinfo->content.encryptedData->encContentInfo.encContent.len = 0;
00392               rv = SECSuccess;
00393            }
00394            if(rv == SECFailure)
00395               goto loser;
00396            break;
00397        case SEC_OID_PKCS7_DATA:
00398            cinfo->content.data = (SECItem *)PORT_ArenaZAlloc(cinfo->poolp,
00399               sizeof(SECItem));
00400            if(cinfo->content.data == NULL)
00401               goto loser;
00402            if(content.len > 0) {
00403               rv = SECITEM_CopyItem(cinfo->poolp,
00404                      cinfo->content.data, &content);
00405            } else {
00406               /* handle case with NULL content */
00407               rv = SECSuccess;
00408            }
00409            if(rv == SECFailure)
00410               goto loser;
00411            break;
00412        default:
00413            goto loser;
00414     }
00415 
00416     return SECSuccess;
00417 
00418 loser:
00419        
00420     return SECFailure;
00421 }
00422 
00423 /* the content of an encrypted data content info is encrypted.
00424  * it is assumed that for encrypted data, that the data has already
00425  * been set and is in the "plainContent" field of the content info.
00426  *
00427  * cinfo is the content info to encrypt
00428  *
00429  * key is the key with which to perform the encryption.  if the
00430  *     algorithm is a password based encryption algorithm, the
00431  *     key is actually a password which will be processed per
00432  *     PKCS #5.
00433  * 
00434  * in the event of an error, SECFailure is returned.  SECSuccess
00435  * indicates a success.
00436  */
00437 SECStatus 
00438 SEC_PKCS7EncryptContents(PRArenaPool *poolp,
00439                       SEC_PKCS7ContentInfo *cinfo,
00440                       SECItem *key,
00441                       void *wincx)
00442 {
00443     SECAlgorithmID *algid   = NULL;
00444     SECItem *       result  = NULL;
00445     SECItem *       src;
00446     SECItem *       dest;
00447     SECItem *       blocked_data = NULL;
00448     void *          mark;
00449     void *          cx;
00450     PK11SymKey *    eKey    = NULL;
00451     PK11SlotInfo *  slot    = NULL;
00452 
00453     CK_MECHANISM    pbeMech;
00454     CK_MECHANISM    cryptoMech;
00455     int             bs;
00456     SECOidTag       algtag;
00457     SECStatus       rv             = SECFailure;
00458     SECItem         c_param;
00459 
00460     if((cinfo == NULL) || (key == NULL))
00461        return SECFailure;
00462 
00463     if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA)
00464        return SECFailure;
00465 
00466     algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);     
00467     if(algid == NULL)
00468        return SECFailure;
00469 
00470     if(poolp == NULL)
00471        poolp = cinfo->poolp;
00472 
00473     mark = PORT_ArenaMark(poolp);
00474     
00475     src = &cinfo->content.encryptedData->encContentInfo.plainContent;
00476     dest = &cinfo->content.encryptedData->encContentInfo.encContent;
00477     algtag = SECOID_GetAlgorithmTag(algid);
00478     c_param.data = NULL;
00479     dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64));
00480     dest->len = (src->len + 64);
00481     if(dest->data == NULL) {
00482        rv = SECFailure;
00483        goto loser;
00484     }
00485 
00486     slot = PK11_GetInternalKeySlot();
00487     if(slot == NULL) {
00488        rv = SECFailure;
00489        goto loser;
00490     }
00491     pbeMech.mechanism = PK11_AlgtagToMechanism(algtag);
00492     result = PK11_ParamFromAlgid(algid);
00493     if (result == NULL) {
00494        rv = SECFailure;
00495        goto loser;
00496     }
00497     pbeMech.pParameter = result->data;
00498     pbeMech.ulParameterLen = result->len;
00499 
00500     eKey = PK11_RawPBEKeyGen(slot, pbeMech.mechanism, result, key, PR_FALSE,
00501                                                          wincx);
00502     if(eKey == NULL) {
00503        rv = SECFailure;
00504        goto loser;
00505     }
00506 
00507     if(PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, key, 
00508                      PR_FALSE) != CKR_OK) {
00509        rv = SECFailure;
00510        goto loser;
00511     }
00512     c_param.data = (unsigned char *)cryptoMech.pParameter;
00513     c_param.len = cryptoMech.ulParameterLen;
00514 
00515     /* block according to PKCS 8 */
00516     bs = PK11_GetBlockSize(cryptoMech.mechanism, &c_param);
00517     rv = SECSuccess;
00518     if(bs) {
00519        char pad_char;
00520        pad_char = (char)(bs - (src->len % bs));
00521        if(src->len % bs) {
00522            rv = SECSuccess;
00523            blocked_data = PK11_BlockData(src, bs);
00524            if(blocked_data) {
00525               PORT_Memset((blocked_data->data + blocked_data->len - (int)pad_char), 
00526                          pad_char, (int)pad_char);
00527            } else {
00528               rv = SECFailure;
00529               goto loser;
00530            }
00531        } else {
00532            blocked_data = SECITEM_DupItem(src);
00533            if(blocked_data) {
00534               blocked_data->data = (unsigned char*)PORT_Realloc(
00535                                             blocked_data->data,
00536                                             blocked_data->len + bs);
00537               if(blocked_data->data) {
00538                   blocked_data->len += bs;
00539                   PORT_Memset((blocked_data->data + src->len), (char)bs, bs);
00540               } else {
00541                   rv = SECFailure;
00542                   goto loser;
00543               }
00544            } else {
00545               rv = SECFailure;
00546               goto loser;
00547            }
00548         }
00549     } else {
00550        blocked_data = SECITEM_DupItem(src);
00551        if(!blocked_data) {
00552            rv = SECFailure;
00553            goto loser;
00554        }
00555     }
00556 
00557     cx = PK11_CreateContextBySymKey(cryptoMech.mechanism, CKA_ENCRYPT,
00558                                 eKey, &c_param);
00559     if(cx == NULL) {
00560        rv = SECFailure;
00561        goto loser;
00562     }
00563 
00564     rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len), 
00565                      (int)(src->len + 64), blocked_data->data, 
00566                      (int)blocked_data->len);
00567     PK11_DestroyContext((PK11Context*)cx, PR_TRUE);
00568 
00569 loser:
00570     /* let success fall through */
00571     if(blocked_data != NULL)
00572        SECITEM_ZfreeItem(blocked_data, PR_TRUE);
00573 
00574     if(result != NULL)
00575        SECITEM_ZfreeItem(result, PR_TRUE);
00576 
00577     if(rv == SECFailure)
00578        PORT_ArenaRelease(poolp, mark);
00579     else 
00580        PORT_ArenaUnmark(poolp, mark);
00581 
00582     if(eKey != NULL)
00583        PK11_FreeSymKey(eKey);
00584 
00585     if(slot != NULL)
00586        PK11_FreeSlot(slot);
00587 
00588     if(c_param.data != NULL) 
00589        SECITEM_ZfreeItem(&c_param, PR_FALSE);
00590        
00591     return rv;
00592 }
00593 
00594 /* the content of an encrypted data content info is decrypted.
00595  * it is assumed that for encrypted data, that the data has already
00596  * been set and is in the "encContent" field of the content info.
00597  *
00598  * cinfo is the content info to decrypt
00599  *
00600  * key is the key with which to perform the decryption.  if the
00601  *     algorithm is a password based encryption algorithm, the
00602  *     key is actually a password which will be processed per
00603  *     PKCS #5.
00604  * 
00605  * in the event of an error, SECFailure is returned.  SECSuccess
00606  * indicates a success.
00607  */
00608 SECStatus 
00609 SEC_PKCS7DecryptContents(PRArenaPool *poolp,
00610                       SEC_PKCS7ContentInfo *cinfo,
00611                       SECItem *key,
00612                       void *wincx)
00613 {
00614     SECAlgorithmID *algid = NULL;
00615     SECOidTag algtag;
00616     SECStatus rv = SECFailure;
00617     SECItem *result = NULL, *dest, *src;
00618     void *mark;
00619 
00620     PK11SymKey *eKey = NULL;
00621     PK11SlotInfo *slot = NULL;
00622     CK_MECHANISM pbeMech, cryptoMech;
00623     void *cx;
00624     SECItem c_param;
00625     int bs;
00626 
00627     if((cinfo == NULL) || (key == NULL))
00628        return SECFailure;
00629 
00630     if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA)
00631        return SECFailure;
00632 
00633     algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);     
00634     if(algid == NULL)
00635        return SECFailure;
00636 
00637     if(poolp == NULL)
00638        poolp = cinfo->poolp;
00639 
00640     mark = PORT_ArenaMark(poolp);
00641     
00642     src = &cinfo->content.encryptedData->encContentInfo.encContent;
00643     dest = &cinfo->content.encryptedData->encContentInfo.plainContent;
00644     algtag = SECOID_GetAlgorithmTag(algid);
00645     c_param.data = NULL;
00646     dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64));
00647     dest->len = (src->len + 64);
00648     if(dest->data == NULL) {
00649        rv = SECFailure;
00650        goto loser;
00651     }
00652 
00653     slot = PK11_GetInternalKeySlot();
00654     if(slot == NULL) {
00655        rv = SECFailure;
00656        goto loser;
00657     }
00658     pbeMech.mechanism = PK11_AlgtagToMechanism(algtag);
00659     result = PK11_ParamFromAlgid(algid);
00660     if (result == NULL) {
00661        rv = SECFailure;
00662        goto loser;
00663     }
00664     pbeMech.pParameter = result->data;
00665     pbeMech.ulParameterLen = result->len;
00666     eKey = PK11_RawPBEKeyGen(slot,pbeMech.mechanism,result,key,PR_FALSE,wincx);
00667     if(eKey == NULL) {
00668        rv = SECFailure;
00669        goto loser;
00670     }
00671 
00672     if(PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, key,
00673                      PR_FALSE) != CKR_OK) {
00674        rv = SECFailure;
00675        goto loser;
00676     }
00677     c_param.data = (unsigned char *)cryptoMech.pParameter;
00678     c_param.len = cryptoMech.ulParameterLen;
00679 
00680     cx = PK11_CreateContextBySymKey(cryptoMech.mechanism, CKA_DECRYPT,
00681                                 eKey, &c_param);
00682     if(cx == NULL) {
00683        rv = SECFailure;
00684        goto loser;
00685     }
00686 
00687     rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len), 
00688                      (int)(src->len + 64), src->data, (int)src->len);
00689     PK11_DestroyContext((PK11Context *)cx, PR_TRUE);
00690 
00691     bs = PK11_GetBlockSize(cryptoMech.mechanism, &c_param);
00692     if(bs) {
00693        /* check for proper badding in block algorithms.  this assumes
00694         * RC2 cbc or a DES cbc variant.  and the padding is thus defined
00695         */
00696        if(((int)dest->data[dest->len-1] <= bs) && 
00697           ((int)dest->data[dest->len-1] > 0)) {
00698            dest->len -= (int)dest->data[dest->len-1];
00699        } else {
00700            rv = SECFailure;
00701            /* set an error ? */
00702        }
00703     } 
00704 
00705 loser:
00706     /* let success fall through */
00707     if(result != NULL)
00708        SECITEM_ZfreeItem(result, PR_TRUE);
00709 
00710     if(rv == SECFailure)
00711        PORT_ArenaRelease(poolp, mark);
00712     else
00713        PORT_ArenaUnmark(poolp, mark);
00714 
00715     if(eKey != NULL)
00716        PK11_FreeSymKey(eKey);
00717 
00718     if(slot != NULL)
00719        PK11_FreeSlot(slot);
00720 
00721     if(c_param.data != NULL) 
00722        SECITEM_ZfreeItem(&c_param, PR_FALSE);
00723        
00724     return rv;
00725 }
00726 
00727 SECItem **
00728 SEC_PKCS7GetCertificateList(SEC_PKCS7ContentInfo *cinfo)
00729 {
00730     switch(SEC_PKCS7ContentType(cinfo))
00731     {
00732        case SEC_OID_PKCS7_SIGNED_DATA:
00733            return cinfo->content.signedData->rawCerts;
00734            break;
00735        default:
00736            return NULL;
00737            break;
00738     }
00739 }
00740 
00741 
00742 int
00743 SEC_PKCS7GetKeyLength(SEC_PKCS7ContentInfo *cinfo)
00744 {
00745   if (cinfo->contentTypeTag->offset == SEC_OID_PKCS7_ENVELOPED_DATA)
00746     return cinfo->content.envelopedData->encContentInfo.keysize;
00747   else
00748     return 0;
00749 }
00750