Back to index

lightning-sunbird  0.9+nobinonly
pk11cert.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  *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 /*
00038  * This file manages PKCS #11 instances of certificates.
00039  */
00040 
00041 #include "secport.h"
00042 #include "seccomon.h"
00043 #include "secmod.h"
00044 #include "secmodi.h"
00045 #include "secmodti.h"
00046 #include "pkcs11.h"
00047 #include "pk11func.h"
00048 #include "cert.h"
00049 #include "certi.h"
00050 #include "secitem.h"
00051 #include "key.h" 
00052 #include "secoid.h"
00053 #include "pkcs7t.h"
00054 #include "cmsreclist.h"
00055 
00056 #include "certdb.h"
00057 #include "secerr.h"
00058 #include "sslerr.h"
00059 
00060 #ifndef NSS_3_4_CODE
00061 #define NSS_3_4_CODE
00062 #endif /* NSS_3_4_CODE */
00063 #include "pki3hack.h"
00064 #include "dev3hack.h"
00065 
00066 #include "devm.h" 
00067 #include "nsspki.h"
00068 #include "pki.h"
00069 #include "pkim.h"
00070 #include "pkitm.h"
00071 #include "pkistore.h" /* to remove temp cert */
00072 #include "devt.h"
00073 
00074 extern const NSSError NSS_ERROR_NOT_FOUND;
00075 extern const NSSError NSS_ERROR_INVALID_CERTIFICATE;
00076 
00077 struct nss3_cert_cbstr {
00078     SECStatus(* callback)(CERTCertificate*, void *);
00079     nssList *cached;
00080     void *arg;
00081 };
00082 
00083 /* Translate from NSSCertificate to CERTCertificate, then pass the latter
00084  * to a callback.
00085  */
00086 static PRStatus convert_cert(NSSCertificate *c, void *arg)
00087 {
00088     CERTCertificate *nss3cert;
00089     SECStatus secrv;
00090     struct nss3_cert_cbstr *nss3cb = (struct nss3_cert_cbstr *)arg;
00091     /* 'c' is not adopted. caller will free it */
00092     nss3cert = STAN_GetCERTCertificate(c);
00093     if (!nss3cert) return PR_FAILURE;
00094     secrv = (*nss3cb->callback)(nss3cert, nss3cb->arg);
00095     return (secrv) ? PR_FAILURE : PR_SUCCESS;
00096 }
00097 
00098 /*
00099  * build a cert nickname based on the token name and the label of the 
00100  * certificate If the label in NULL, build a label based on the ID.
00101  */
00102 static int toHex(int x) { return (x < 10) ? (x+'0') : (x+'a'-10); }
00103 #define MAX_CERT_ID 4
00104 #define DEFAULT_STRING "Cert ID "
00105 static char *
00106 pk11_buildNickname(PK11SlotInfo *slot,CK_ATTRIBUTE *cert_label,
00107                      CK_ATTRIBUTE *key_label, CK_ATTRIBUTE *cert_id)
00108 {
00109     int prefixLen = PORT_Strlen(slot->token_name);
00110     int suffixLen = 0;
00111     char *suffix = NULL;
00112     char buildNew[sizeof(DEFAULT_STRING)+MAX_CERT_ID*2];
00113     char *next,*nickname;
00114 
00115     if (cert_label && (cert_label->ulValueLen)) {
00116        suffixLen = cert_label->ulValueLen;
00117        suffix = (char*)cert_label->pValue;
00118     } else if (key_label && (key_label->ulValueLen)) {
00119        suffixLen = key_label->ulValueLen;
00120        suffix = (char*)key_label->pValue;
00121     } else if (cert_id && cert_id->ulValueLen > 0) {
00122        int i,first = cert_id->ulValueLen - MAX_CERT_ID;
00123        int offset = sizeof(DEFAULT_STRING);
00124        char *idValue = (char *)cert_id->pValue;
00125 
00126        PORT_Memcpy(buildNew,DEFAULT_STRING,sizeof(DEFAULT_STRING)-1);
00127        next = buildNew + offset;
00128        if (first < 0) first = 0;
00129        for (i=first; i < (int) cert_id->ulValueLen; i++) {
00130               *next++ = toHex((idValue[i] >> 4) & 0xf);
00131               *next++ = toHex(idValue[i] & 0xf);
00132        }
00133        *next++ = 0;
00134        suffix = buildNew;
00135        suffixLen = PORT_Strlen(buildNew);
00136     } else {
00137        PORT_SetError( SEC_ERROR_LIBRARY_FAILURE );
00138        return NULL;
00139     }
00140 
00141     /* if is internal key slot, add code to skip the prefix!! */
00142     next = nickname = (char *)PORT_Alloc(prefixLen+1+suffixLen+1);
00143     if (nickname == NULL) return NULL;
00144 
00145     PORT_Memcpy(next,slot->token_name,prefixLen);
00146     next += prefixLen;
00147     *next++ = ':';
00148     PORT_Memcpy(next,suffix,suffixLen);
00149     next += suffixLen;
00150     *next++ = 0;
00151     return nickname;
00152 }
00153 
00154 PRBool
00155 PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert,
00156                                           CK_OBJECT_HANDLE certID)
00157 {
00158     CK_OBJECT_CLASS theClass;
00159 
00160     if (slot == NULL) return PR_FALSE;
00161     if (cert == NULL) return PR_FALSE;
00162 
00163     theClass = CKO_PRIVATE_KEY;
00164     if (pk11_LoginStillRequired(slot,NULL)) {
00165        theClass = CKO_PUBLIC_KEY;
00166     }
00167     if (PK11_MatchItem(slot, certID , theClass) != CK_INVALID_HANDLE) {
00168        return PR_TRUE;
00169     }
00170 
00171    if (theClass == CKO_PUBLIC_KEY) {
00172        SECKEYPublicKey *pubKey= CERT_ExtractPublicKey(cert);
00173        CK_ATTRIBUTE theTemplate;
00174 
00175        if (pubKey == NULL) {
00176           return PR_FALSE;
00177        }
00178 
00179        PK11_SETATTRS(&theTemplate,0,NULL,0);
00180        switch (pubKey->keyType) {
00181        case rsaKey:
00182            PK11_SETATTRS(&theTemplate,CKA_MODULUS, pubKey->u.rsa.modulus.data,
00183                                           pubKey->u.rsa.modulus.len);
00184            break;
00185        case dsaKey:
00186            PK11_SETATTRS(&theTemplate,CKA_VALUE, pubKey->u.dsa.publicValue.data,
00187                                           pubKey->u.dsa.publicValue.len);
00188            break;
00189        case dhKey:
00190            PK11_SETATTRS(&theTemplate,CKA_VALUE, pubKey->u.dh.publicValue.data,
00191                                           pubKey->u.dh.publicValue.len);
00192            break;
00193        case ecKey:
00194            PK11_SETATTRS(&theTemplate,CKA_EC_POINT, 
00195                        pubKey->u.ec.publicValue.data,
00196                        pubKey->u.ec.publicValue.len);
00197            break;
00198        case keaKey:
00199        case fortezzaKey:
00200        case nullKey:
00201            /* fall through and return false */
00202            break;
00203        }
00204 
00205        if (theTemplate.ulValueLen == 0) {
00206            SECKEY_DestroyPublicKey(pubKey);
00207            return PR_FALSE;
00208        }
00209        pk11_SignedToUnsigned(&theTemplate);
00210        if (pk11_FindObjectByTemplate(slot,&theTemplate,1) != CK_INVALID_HANDLE) {
00211            SECKEY_DestroyPublicKey(pubKey);
00212            return PR_TRUE;
00213        }
00214        SECKEY_DestroyPublicKey(pubKey);
00215     }
00216     return PR_FALSE;
00217 }
00218 
00219 /*
00220  * Check out if a cert has ID of zero. This is a magic ID that tells
00221  * NSS that this cert may be an automagically trusted cert.
00222  * The Cert has to be self signed as well. That check is done elsewhere.
00223  *  
00224  */
00225 PRBool
00226 pk11_isID0(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID)
00227 {
00228     CK_ATTRIBUTE keyID = {CKA_ID, NULL, 0};
00229     PRBool isZero = PR_FALSE;
00230     int i;
00231     CK_RV crv;
00232 
00233 
00234     crv = PK11_GetAttributes(NULL,slot,certID,&keyID,1);
00235     if (crv != CKR_OK) {
00236        return isZero;
00237     }
00238 
00239     if (keyID.ulValueLen != 0) {
00240        char *value = (char *)keyID.pValue;
00241        isZero = PR_TRUE; /* ID exists, may be zero */
00242        for (i=0; i < (int) keyID.ulValueLen; i++) {
00243            if (value[i] != 0) {
00244               isZero = PR_FALSE; /* nope */
00245               break;
00246            }
00247        }
00248     }
00249     PORT_Free(keyID.pValue);
00250     return isZero;
00251 
00252 }
00253 
00254 /*
00255  * Create an NSSCertificate from a slot/certID pair, return it as a
00256  * CERTCertificate.
00257  */
00258 static CERTCertificate
00259 *pk11_fastCert(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, 
00260                      CK_ATTRIBUTE *privateLabel, char **nickptr)
00261 {
00262     NSSCertificate *c;
00263     nssCryptokiObject *co;
00264     nssPKIObject *pkio;
00265     NSSToken *token;
00266     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
00267 
00268     /* Get the cryptoki object from the handle */
00269     token = PK11Slot_GetNSSToken(slot);
00270     co = nssCryptokiObject_Create(token, token->defaultSession, certID);
00271     if (!co) {
00272        return NULL;
00273     }
00274 
00275     /* Create a PKI object from the cryptoki instance */
00276     pkio = nssPKIObject_Create(NULL, co, td, NULL, nssPKIMonitor);
00277     if (!pkio) {
00278        nssCryptokiObject_Destroy(co);
00279        return NULL;
00280     }
00281 
00282     /* Create a certificate */
00283     c = nssCertificate_Create(pkio);
00284     if (!c) {
00285        nssPKIObject_Destroy(pkio);
00286        return NULL;
00287     }
00288 
00289     nssTrustDomain_AddCertsToCache(td, &c, 1);
00290 
00291     /* Build the old-fashioned nickname */
00292     if ((nickptr) && (co->label)) {
00293        CK_ATTRIBUTE label, id;
00294        label.type = CKA_LABEL;
00295        label.pValue = co->label;
00296        label.ulValueLen = PORT_Strlen(co->label);
00297        id.type = CKA_ID;
00298        id.pValue = c->id.data;
00299        id.ulValueLen = c->id.size;
00300        *nickptr = pk11_buildNickname(slot, &label, privateLabel, &id);
00301     }
00302     return STAN_GetCERTCertificateOrRelease(c);
00303 }
00304 
00305 /*
00306  * Build an CERTCertificate structure from a PKCS#11 object ID.... certID
00307  * Must be a CertObject. This code does not explicitly checks that.
00308  */
00309 CERTCertificate *
00310 PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID,
00311                                           CK_ATTRIBUTE *privateLabel)
00312 {
00313     char * nickname = NULL;
00314     CERTCertificate *cert = NULL;
00315     CERTCertTrust *trust;
00316     PRBool isFortezzaRootCA = PR_FALSE;
00317     PRBool swapNickname = PR_FALSE;
00318 
00319     cert = pk11_fastCert(slot,certID,privateLabel, &nickname);
00320     if (cert == NULL) goto loser;
00321        
00322     if (nickname) {
00323        if (cert->nickname != NULL) {
00324               cert->dbnickname = cert->nickname;
00325        } 
00326        cert->nickname = PORT_ArenaStrdup(cert->arena,nickname);
00327        PORT_Free(nickname);
00328        nickname = NULL;
00329        swapNickname = PR_TRUE;
00330     }
00331 
00332     /* remember where this cert came from.... If we have just looked
00333      * it up from the database and it already has a slot, don't add a new
00334      * one. */
00335     if (cert->slot == NULL) {
00336        cert->slot = PK11_ReferenceSlot(slot);
00337        cert->pkcs11ID = certID;
00338        cert->ownSlot = PR_TRUE;
00339        cert->series = slot->series;
00340     }
00341 
00342     trust = (CERTCertTrust*)PORT_ArenaAlloc(cert->arena, sizeof(CERTCertTrust));
00343     if (trust == NULL) goto loser;
00344     PORT_Memset(trust,0, sizeof(CERTCertTrust));
00345     cert->trust = trust;
00346 
00347     
00348 
00349     if(! pk11_HandleTrustObject(slot, cert, trust) ) {
00350        unsigned int type;
00351 
00352        /* build some cert trust flags */
00353        if (CERT_IsCACert(cert, &type)) {
00354            unsigned int trustflags = CERTDB_VALID_CA;
00355           
00356            /* Allow PKCS #11 modules to give us trusted CA's. We only accept
00357             * valid CA's which are self-signed here. They must have an object
00358             * ID of '0'.  */ 
00359            if (pk11_isID0(slot,certID) && 
00360               SECITEM_CompareItem(&cert->derSubject,&cert->derIssuer)
00361                                                     == SECEqual) {
00362               trustflags |= CERTDB_TRUSTED_CA;
00363               /* is the slot a fortezza card? allow the user or
00364                * admin to turn on objectSigning, but don't turn
00365                * full trust on explicitly */
00366               if (PK11_DoesMechanism(slot,CKM_KEA_KEY_DERIVE)) {
00367                   trust->objectSigningFlags |= CERTDB_VALID_CA;
00368                   isFortezzaRootCA = PR_TRUE;
00369               }
00370            }
00371            if ((type & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) {
00372               trust->sslFlags |= trustflags;
00373            }
00374            if ((type & NS_CERT_TYPE_EMAIL_CA) == NS_CERT_TYPE_EMAIL_CA) {
00375               trust->emailFlags |= trustflags;
00376            }
00377            if ((type & NS_CERT_TYPE_OBJECT_SIGNING_CA) 
00378                                    == NS_CERT_TYPE_OBJECT_SIGNING_CA) {
00379               trust->objectSigningFlags |= trustflags;
00380            }
00381        }
00382     }
00383 
00384     if (PK11_IsUserCert(slot,cert,certID)) {
00385        trust->sslFlags |= CERTDB_USER;
00386        trust->emailFlags |= CERTDB_USER;
00387        /*    trust->objectSigningFlags |= CERTDB_USER; */
00388     }
00389 
00390     return cert;
00391 
00392 loser:
00393     if (nickname) PORT_Free(nickname);
00394     if (cert) CERT_DestroyCertificate(cert);
00395     return NULL;
00396 }
00397 
00398        
00399 /*
00400  * Build get a certificate from a private key
00401  */
00402 CERTCertificate *
00403 PK11_GetCertFromPrivateKey(SECKEYPrivateKey *privKey)
00404 {
00405     PK11SlotInfo *slot = privKey->pkcs11Slot;
00406     CK_OBJECT_HANDLE handle = privKey->pkcs11ID;
00407     CK_OBJECT_HANDLE certID = 
00408               PK11_MatchItem(slot,handle,CKO_CERTIFICATE);
00409     CERTCertificate *cert;
00410 
00411     if (certID == CK_INVALID_HANDLE) {
00412        PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
00413        return NULL;
00414     }
00415     cert = PK11_MakeCertFromHandle(slot,certID,NULL);
00416     return (cert);
00417 
00418 }
00419 
00420 /*
00421  * delete a cert and it's private key (if no other certs are pointing to the
00422  * private key.
00423  */
00424 SECStatus
00425 PK11_DeleteTokenCertAndKey(CERTCertificate *cert,void *wincx)
00426 {
00427     SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert,wincx);
00428     CK_OBJECT_HANDLE pubKey;
00429     PK11SlotInfo *slot = NULL;
00430 
00431     pubKey = pk11_FindPubKeyByAnyCert(cert, &slot, wincx);
00432     if (privKey) {
00433        /* For 3.4, utilize the generic cert delete function */
00434        SEC_DeletePermCertificate(cert);
00435        PK11_DeleteTokenPrivateKey(privKey, PR_FALSE);
00436     }
00437     if ((pubKey != CK_INVALID_HANDLE) && (slot != NULL)) { 
00438        PK11_DestroyTokenObject(slot,pubKey);
00439         PK11_FreeSlot(slot);
00440     }
00441     return SECSuccess;
00442 }
00443 
00444 /*
00445  * cert callback structure
00446  */
00447 typedef struct pk11DoCertCallbackStr {
00448        SECStatus(* callback)(PK11SlotInfo *slot, CERTCertificate*, void *);
00449        SECStatus(* noslotcallback)(CERTCertificate*, void *);
00450        SECStatus(* itemcallback)(CERTCertificate*, SECItem *, void *);
00451        void *callbackArg;
00452 } pk11DoCertCallback;
00453 
00454 
00455 typedef struct pk11CertCallbackStr {
00456        SECStatus(* callback)(CERTCertificate*,SECItem *,void *);
00457        void *callbackArg;
00458 } pk11CertCallback;
00459 
00460 struct fake_der_cb_argstr
00461 {
00462     SECStatus(* callback)(CERTCertificate*, SECItem *, void *);
00463     void *arg;
00464 };
00465 
00466 static SECStatus fake_der_cb(CERTCertificate *c, void *a)
00467 {
00468     struct fake_der_cb_argstr *fda = (struct fake_der_cb_argstr *)a;
00469     return (*fda->callback)(c, &c->derCert, fda->arg);
00470 }
00471 
00472 /*
00473  * Extract all the certs on a card from a slot.
00474  */
00475 SECStatus
00476 PK11_TraverseSlotCerts(SECStatus(* callback)(CERTCertificate*,SECItem *,void *),
00477                                           void *arg, void *wincx) 
00478 {
00479     NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain();
00480     struct fake_der_cb_argstr fda;
00481     struct nss3_cert_cbstr pk11cb;
00482 
00483     /* authenticate to the tokens first */
00484     (void) pk11_TraverseAllSlots( NULL, NULL, PR_TRUE, wincx);
00485 
00486     fda.callback = callback;
00487     fda.arg = arg;
00488     pk11cb.callback = fake_der_cb;
00489     pk11cb.arg = &fda;
00490     NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb);
00491     return SECSuccess;
00492 }
00493 
00494 static void
00495 transfer_token_certs_to_collection(nssList *certList, NSSToken *token, 
00496                                    nssPKIObjectCollection *collection)
00497 {
00498     NSSCertificate **certs;
00499     PRUint32 i, count;
00500     NSSToken **tokens, **tp;
00501     count = nssList_Count(certList);
00502     if (count == 0) {
00503        return;
00504     }
00505     certs = nss_ZNEWARRAY(NULL, NSSCertificate *, count);
00506     if (!certs) {
00507        return;
00508     }
00509     nssList_GetArray(certList, (void **)certs, count);
00510     for (i=0; i<count; i++) {
00511        tokens = nssPKIObject_GetTokens(&certs[i]->object, NULL);
00512        if (tokens) {
00513            for (tp = tokens; *tp; tp++) {
00514               if (*tp == token) {
00515                   nssPKIObjectCollection_AddObject(collection, 
00516                                                    (nssPKIObject *)certs[i]);
00517               }
00518            }
00519            nssTokenArray_Destroy(tokens);
00520        }
00521        CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(certs[i]));
00522     }
00523     nss_ZFreeIf(certs);
00524 }
00525 
00526 CERTCertificate *
00527 PK11_FindCertFromNickname(char *nickname, void *wincx) 
00528 {
00529     PRStatus status;
00530     CERTCertificate *rvCert = NULL;
00531     NSSCertificate *cert = NULL;
00532     NSSCertificate **certs = NULL;
00533     static const NSSUsage usage = {PR_TRUE /* ... */ };
00534     NSSToken *token;
00535     NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain();
00536     PK11SlotInfo *slot = NULL;
00537     SECStatus rv;
00538     char *nickCopy;
00539     char *delimit = NULL;
00540     char *tokenName;
00541 
00542     nickCopy = PORT_Strdup(nickname);
00543     if ((delimit = PORT_Strchr(nickCopy,':')) != NULL) {
00544        tokenName = nickCopy;
00545        nickname = delimit + 1;
00546        *delimit = '\0';
00547        /* find token by name */
00548        token = NSSTrustDomain_FindTokenByName(defaultTD, (NSSUTF8 *)tokenName);
00549        if (token) {
00550               slot = PK11_ReferenceSlot(token->pk11slot);
00551        }
00552        *delimit = ':';
00553     } else {
00554        slot = PK11_GetInternalKeySlot();
00555        token = PK11Slot_GetNSSToken(slot);
00556     }
00557     if (token) {
00558        nssList *certList;
00559        nssCryptokiObject **instances;
00560        nssPKIObjectCollection *collection;
00561        nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
00562        if (!PK11_IsPresent(slot)) {
00563            goto loser;
00564        }
00565        rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx);
00566        if (rv != SECSuccess) {
00567            goto loser;
00568        }
00569        collection = nssCertificateCollection_Create(defaultTD, NULL);
00570        if (!collection) {
00571            goto loser;
00572        }
00573        certList = nssList_Create(NULL, PR_FALSE);
00574        if (!certList) {
00575            nssPKIObjectCollection_Destroy(collection);
00576            goto loser;
00577        }
00578        (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, 
00579                                                          nickname, 
00580                                                          certList);
00581        transfer_token_certs_to_collection(certList, token, collection);
00582        instances = nssToken_FindCertificatesByNickname(token,
00583                                                        NULL,
00584                                                        nickname,
00585                                                        tokenOnly,
00586                                                        0,
00587                                                        &status);
00588        nssPKIObjectCollection_AddInstances(collection, instances, 0);
00589        nss_ZFreeIf(instances);
00590        /* if it wasn't found, repeat the process for email address */
00591        if (nssPKIObjectCollection_Count(collection) == 0 &&
00592            PORT_Strchr(nickname, '@') != NULL) 
00593        {
00594            char* lowercaseName = CERT_FixupEmailAddr(nickname);
00595            if (lowercaseName) {
00596               (void)nssTrustDomain_GetCertsForEmailAddressFromCache(defaultTD, 
00597                                                               lowercaseName, 
00598                                                               certList);
00599               transfer_token_certs_to_collection(certList, token, collection);
00600               instances = nssToken_FindCertificatesByEmail(token,
00601                                                       NULL,
00602                                                       lowercaseName,
00603                                                       tokenOnly,
00604                                                       0,
00605                                                       &status);
00606               nssPKIObjectCollection_AddInstances(collection, instances, 0);
00607               nss_ZFreeIf(instances);
00608               PORT_Free(lowercaseName);
00609            }
00610        }
00611        certs = nssPKIObjectCollection_GetCertificates(collection, 
00612                                                       NULL, 0, NULL);
00613        nssPKIObjectCollection_Destroy(collection);
00614        if (certs) {
00615            cert = nssCertificateArray_FindBestCertificate(certs, NULL, 
00616                                                           &usage, NULL);
00617            if (cert) {
00618               rvCert = STAN_GetCERTCertificateOrRelease(cert);
00619            }
00620            nssCertificateArray_Destroy(certs);
00621        }
00622        nssList_Destroy(certList);
00623     }
00624     if (slot) {
00625        PK11_FreeSlot(slot);
00626     }
00627     if (nickCopy) PORT_Free(nickCopy);
00628     return rvCert;
00629 loser:
00630     if (slot) {
00631        PK11_FreeSlot(slot);
00632     }
00633     if (nickCopy) PORT_Free(nickCopy);
00634     return NULL;
00635 }
00636 
00637 CERTCertList *
00638 PK11_FindCertsFromNickname(char *nickname, void *wincx) 
00639 {
00640     char *nickCopy;
00641     char *delimit = NULL;
00642     char *tokenName;
00643     int i;
00644     CERTCertList *certList = NULL;
00645     nssPKIObjectCollection *collection = NULL;
00646     NSSCertificate **foundCerts = NULL;
00647     NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain();
00648     NSSCertificate *c;
00649     NSSToken *token;
00650     PK11SlotInfo *slot;
00651     SECStatus rv;
00652 
00653     nickCopy = PORT_Strdup(nickname);
00654     if ((delimit = PORT_Strchr(nickCopy,':')) != NULL) {
00655        tokenName = nickCopy;
00656        nickname = delimit + 1;
00657        *delimit = '\0';
00658        /* find token by name */
00659        token = NSSTrustDomain_FindTokenByName(defaultTD, (NSSUTF8 *)tokenName);
00660        if (token) {
00661            slot = PK11_ReferenceSlot(token->pk11slot);
00662        } else {
00663            slot = NULL;
00664        }
00665        *delimit = ':';
00666     } else {
00667        slot = PK11_GetInternalKeySlot();
00668        token = PK11Slot_GetNSSToken(slot);
00669     }
00670     if (token) {
00671        PRStatus status;
00672        nssList *nameList;
00673        nssCryptokiObject **instances;
00674        nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
00675        rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx);
00676        if (rv != SECSuccess) {
00677            PK11_FreeSlot(slot);
00678            if (nickCopy) PORT_Free(nickCopy);
00679            return NULL;
00680        }
00681        collection = nssCertificateCollection_Create(defaultTD, NULL);
00682        if (!collection) {
00683            PK11_FreeSlot(slot);
00684            if (nickCopy) PORT_Free(nickCopy);
00685            return NULL;
00686        }
00687        nameList = nssList_Create(NULL, PR_FALSE);
00688        if (!nameList) {
00689            PK11_FreeSlot(slot);
00690            if (nickCopy) PORT_Free(nickCopy);
00691            return NULL;
00692        }
00693        (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD,
00694                                                          nickname, 
00695                                                          nameList);
00696        transfer_token_certs_to_collection(nameList, token, collection);
00697        instances = nssToken_FindCertificatesByNickname(token,
00698                                                        NULL,
00699                                                        nickname,
00700                                                        tokenOnly,
00701                                                        0,
00702                                                        &status);
00703        nssPKIObjectCollection_AddInstances(collection, instances, 0);
00704        nss_ZFreeIf(instances);
00705 
00706         /* if it wasn't found, repeat the process for email address */
00707         if (nssPKIObjectCollection_Count(collection) == 0 &&
00708             PORT_Strchr(nickname, '@') != NULL) 
00709         {
00710             char* lowercaseName = CERT_FixupEmailAddr(nickname);
00711             if (lowercaseName) {
00712                 (void)nssTrustDomain_GetCertsForEmailAddressFromCache(defaultTD, 
00713                                                                       lowercaseName, 
00714                                                                       nameList);
00715                 transfer_token_certs_to_collection(nameList, token, collection);
00716                 instances = nssToken_FindCertificatesByEmail(token,
00717                                                              NULL,
00718                                                              lowercaseName,
00719                                                              tokenOnly,
00720                                                              0,
00721                                                              &status);
00722                 nssPKIObjectCollection_AddInstances(collection, instances, 0);
00723                 nss_ZFreeIf(instances);
00724                 PORT_Free(lowercaseName);
00725             }
00726         }
00727 
00728         nssList_Destroy(nameList);
00729        foundCerts = nssPKIObjectCollection_GetCertificates(collection,
00730                                                            NULL, 0, NULL);
00731        nssPKIObjectCollection_Destroy(collection);
00732     }
00733     if (slot) {
00734        PK11_FreeSlot(slot);
00735     }
00736     if (nickCopy) PORT_Free(nickCopy);
00737     if (foundCerts) {
00738        PRTime now = PR_Now();
00739        certList = CERT_NewCertList();
00740        for (i=0, c = *foundCerts; c; c = foundCerts[++i]) {
00741            CERTCertificate *certCert = STAN_GetCERTCertificateOrRelease(c);
00742            /* c may be invalid after this, don't reference it */
00743            if (certCert) {
00744                /* CERT_AddCertToListSorted adopts certCert  */
00745               CERT_AddCertToListSorted(certList, certCert,
00746                      CERT_SortCBValidity, &now);
00747            }
00748        }
00749        if (CERT_LIST_HEAD(certList) == NULL) {
00750            CERT_DestroyCertList(certList);
00751            certList = NULL;
00752        }
00753        /* all the certs have been adopted or freed, free the  raw array */
00754        nss_ZFreeIf(foundCerts);
00755     }
00756     return certList;
00757 }
00758 
00759 /*
00760  * extract a key ID for a certificate...
00761  * NOTE: We call this function from PKCS11.c If we ever use
00762  * pkcs11 to extract the public key (we currently do not), this will break.
00763  */
00764 SECItem *
00765 PK11_GetPubIndexKeyID(CERTCertificate *cert) {
00766     SECKEYPublicKey *pubk;
00767     SECItem *newItem = NULL;
00768 
00769     pubk = CERT_ExtractPublicKey(cert);
00770     if (pubk == NULL) return NULL;
00771 
00772     switch (pubk->keyType) {
00773     case rsaKey:
00774        newItem = SECITEM_DupItem(&pubk->u.rsa.modulus);
00775        break;
00776     case dsaKey:
00777         newItem = SECITEM_DupItem(&pubk->u.dsa.publicValue);
00778        break;
00779     case dhKey:
00780         newItem = SECITEM_DupItem(&pubk->u.dh.publicValue);
00781        break;
00782     case ecKey:
00783         newItem = SECITEM_DupItem(&pubk->u.ec.publicValue);
00784        break;
00785     case fortezzaKey:
00786     default:
00787        newItem = NULL; /* Fortezza Fix later... */
00788     }
00789     SECKEY_DestroyPublicKey(pubk);
00790     /* make hash of it */
00791     return newItem;
00792 }
00793 
00794 /*
00795  * generate a CKA_ID from a certificate.
00796  */
00797 SECItem *
00798 pk11_mkcertKeyID(CERTCertificate *cert) {
00799     SECItem *pubKeyData = PK11_GetPubIndexKeyID(cert) ;
00800     SECItem *certCKA_ID;
00801 
00802     if (pubKeyData == NULL) return NULL;
00803     
00804     certCKA_ID = PK11_MakeIDFromPubKey(pubKeyData);
00805     SECITEM_FreeItem(pubKeyData,PR_TRUE);
00806     return certCKA_ID;
00807 }
00808 
00809 /*
00810  * Write the cert into the token.
00811  */
00812 SECStatus
00813 PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, 
00814               CK_OBJECT_HANDLE key, char *nickname, PRBool includeTrust) 
00815 {
00816     PRStatus status;
00817     NSSCertificate *c;
00818     nssCryptokiObject *keyobj, *certobj;
00819     NSSToken *token = PK11Slot_GetNSSToken(slot);
00820     SECItem *keyID = pk11_mkcertKeyID(cert);
00821     char *emailAddr = NULL;
00822     nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};
00823     nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE};
00824 
00825     if (keyID == NULL) {
00826        goto loser;
00827     }
00828 
00829     if (PK11_IsInternal(slot) && cert->emailAddr && cert->emailAddr[0]) {
00830        emailAddr = cert->emailAddr;
00831     }
00832 
00833     /* need to get the cert as a stan cert */
00834     if (cert->nssCertificate) {
00835        c = cert->nssCertificate;
00836     } else {
00837        c = STAN_GetNSSCertificate(cert);
00838     }
00839 
00840     if (c->object.cryptoContext) {
00841        /* Delete the temp instance */
00842        NSSCryptoContext *cc = c->object.cryptoContext;
00843        nssCertificateStore_Lock(cc->certStore, &lockTrace);
00844        nssCertificateStore_RemoveCertLOCKED(cc->certStore, c);
00845        nssCertificateStore_Unlock(cc->certStore, &lockTrace, &unlockTrace);
00846         nssCertificateStore_Check(&lockTrace, &unlockTrace);
00847        c->object.cryptoContext = NULL;
00848        cert->istemp = PR_FALSE;
00849        cert->isperm = PR_TRUE;
00850     }
00851 
00852     /* set the id for the cert */
00853     nssItem_Create(c->object.arena, &c->id, keyID->len, keyID->data);
00854     if (!c->id.data) {
00855        goto loser;
00856     }
00857 
00858     if (key != CK_INVALID_HANDLE) {
00859        /* create an object for the key, ... */
00860        keyobj = nss_ZNEW(NULL, nssCryptokiObject);
00861        if (!keyobj) {
00862            goto loser;
00863        }
00864        keyobj->token = nssToken_AddRef(token);
00865        keyobj->handle = key;
00866        keyobj->isTokenObject = PR_TRUE;
00867 
00868        /* ... in order to set matching attributes for the key */
00869        status = nssCryptokiPrivateKey_SetCertificate(keyobj, NULL, nickname, 
00870                                                      &c->id, &c->subject);
00871        nssCryptokiObject_Destroy(keyobj);
00872        if (status != PR_SUCCESS) {
00873            goto loser;
00874        }
00875     }
00876 
00877     /* do the token import */
00878     certobj = nssToken_ImportCertificate(token, NULL,
00879                                          NSSCertificateType_PKIX,
00880                                          &c->id,
00881                                          nickname,
00882                                          &c->encoding,
00883                                          &c->issuer,
00884                                          &c->subject,
00885                                          &c->serial,
00886                                     emailAddr,
00887                                          PR_TRUE);
00888     if (!certobj) {
00889        if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE) {
00890            PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL);
00891            SECITEM_FreeItem(keyID,PR_TRUE);
00892            return SECFailure;
00893        }
00894        goto loser;
00895     }
00896     /* add the new instance to the cert, force an update of the
00897      * CERTCertificate, and finish
00898      */
00899     nssPKIObject_AddInstance(&c->object, certobj);
00900     nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1);
00901     (void)STAN_ForceCERTCertificateUpdate(c);
00902     SECITEM_FreeItem(keyID,PR_TRUE);
00903     return SECSuccess;
00904 loser:
00905     SECITEM_FreeItem(keyID,PR_TRUE);
00906     PORT_SetError(SEC_ERROR_ADDING_CERT);
00907     return SECFailure;
00908 }
00909 
00910 SECStatus
00911 PK11_ImportDERCert(PK11SlotInfo *slot, SECItem *derCert,
00912               CK_OBJECT_HANDLE key, char *nickname, PRBool includeTrust) {
00913     CERTCertificate *cert;
00914     SECStatus rv;
00915 
00916     cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
00917                                    derCert, NULL, PR_FALSE, PR_TRUE);
00918     if (cert == NULL) return SECFailure;
00919 
00920     rv = PK11_ImportCert(slot, cert, key, nickname, includeTrust);
00921     CERT_DestroyCertificate (cert);
00922     return rv;
00923 }
00924 
00925 /*
00926  * get a certificate handle, look at the cached handle first..
00927  */
00928 CK_OBJECT_HANDLE
00929 pk11_getcerthandle(PK11SlotInfo *slot, CERTCertificate *cert, 
00930                                    CK_ATTRIBUTE *theTemplate,int tsize)
00931 {
00932     CK_OBJECT_HANDLE certh;
00933 
00934     if (cert->slot == slot) {
00935        certh = cert->pkcs11ID;
00936        if ((certh == CK_INVALID_HANDLE) ||
00937                      (cert->series != slot->series)) {
00938             certh = pk11_FindObjectByTemplate(slot,theTemplate,tsize);
00939             cert->pkcs11ID = certh;
00940             cert->series = slot->series;
00941        }
00942     } else {
00943        certh = pk11_FindObjectByTemplate(slot,theTemplate,tsize);
00944     }
00945     return certh;
00946 }
00947 
00948 /*
00949  * return the private key From a given Cert
00950  */
00951 SECKEYPrivateKey *
00952 PK11_FindPrivateKeyFromCert(PK11SlotInfo *slot, CERTCertificate *cert,
00953                                                          void *wincx) {
00954     int err;
00955     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
00956     CK_ATTRIBUTE theTemplate[] = {
00957        { CKA_VALUE, NULL, 0 },
00958        { CKA_CLASS, NULL, 0 }
00959     };
00960     /* if you change the array, change the variable below as well */
00961     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
00962     CK_OBJECT_HANDLE certh;
00963     CK_OBJECT_HANDLE keyh;
00964     CK_ATTRIBUTE *attrs = theTemplate;
00965     PRBool needLogin;
00966     SECStatus rv;
00967 
00968     PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, 
00969                                           cert->derCert.len); attrs++;
00970     PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass));
00971 
00972     /*
00973      * issue the find
00974      */
00975     rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx);
00976     if (rv != SECSuccess) {
00977        return NULL;
00978     }
00979 
00980     certh = pk11_getcerthandle(slot,cert,theTemplate,tsize);
00981     if (certh == CK_INVALID_HANDLE) {
00982        return NULL;
00983     }
00984     /*
00985      * prevent a login race condition. If slot is logged in between
00986      * our call to pk11_LoginStillRequired and the 
00987      * PK11_MatchItem. The matchItem call will either succeed, or
00988      * we will call it one more time after calling PK11_Authenticate 
00989      * (which is a noop on an authenticated token).
00990      */
00991     needLogin = pk11_LoginStillRequired(slot,wincx);
00992     keyh = PK11_MatchItem(slot,certh,CKO_PRIVATE_KEY);
00993     if ((keyh == CK_INVALID_HANDLE) && needLogin &&
00994                         (SSL_ERROR_NO_CERTIFICATE == (err = PORT_GetError()) ||
00995                       SEC_ERROR_TOKEN_NOT_LOGGED_IN == err )) {
00996        /* try it again authenticated */
00997        rv = PK11_Authenticate(slot, PR_TRUE, wincx);
00998        if (rv != SECSuccess) {
00999            return NULL;
01000        }
01001        keyh = PK11_MatchItem(slot,certh,CKO_PRIVATE_KEY);
01002     }
01003     if (keyh == CK_INVALID_HANDLE) { 
01004        return NULL; 
01005     }
01006     return PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyh, wincx);
01007 } 
01008 
01009 /*
01010  * import a cert for a private key we have already generated. Set the label
01011  * on both to be the nickname. This is for the Key Gen, orphaned key case.
01012  */
01013 PK11SlotInfo *
01014 PK11_KeyForCertExists(CERTCertificate *cert, CK_OBJECT_HANDLE *keyPtr, 
01015                                                         void *wincx) {
01016     PK11SlotList *list;
01017     PK11SlotListElement *le;
01018     SECItem *keyID;
01019     CK_OBJECT_HANDLE key;
01020     PK11SlotInfo *slot = NULL;
01021     SECStatus rv;
01022     int err;
01023 
01024     keyID = pk11_mkcertKeyID(cert);
01025     /* get them all! */
01026     list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx);
01027     if ((keyID == NULL) || (list == NULL)) {
01028        if (keyID) SECITEM_FreeItem(keyID,PR_TRUE);
01029        if (list) PK11_FreeSlotList(list);
01030        return NULL;
01031     }
01032 
01033     /* Look for the slot that holds the Key */
01034     for (le = list->head ; le; le = le->next) {
01035        /*
01036         * prevent a login race condition. If le->slot is logged in between
01037         * our call to pk11_LoginStillRequired and the 
01038         * pk11_FindPrivateKeyFromCertID, the find will either succeed, or
01039         * we will call it one more time after calling PK11_Authenticate 
01040         * (which is a noop on an authenticated token).
01041         */
01042        PRBool needLogin = pk11_LoginStillRequired(le->slot,wincx);
01043        key = pk11_FindPrivateKeyFromCertID(le->slot,keyID);
01044        if ((key == CK_INVALID_HANDLE) && needLogin &&
01045                      (SSL_ERROR_NO_CERTIFICATE == (err = PORT_GetError()) ||
01046                       SEC_ERROR_TOKEN_NOT_LOGGED_IN == err )) {
01047            /* authenticate and try again */
01048            rv = PK11_Authenticate(le->slot, PR_TRUE, wincx);
01049            if (rv != SECSuccess) continue;
01050            key = pk11_FindPrivateKeyFromCertID(le->slot,keyID);
01051        }
01052        if (key != CK_INVALID_HANDLE) {
01053            slot = PK11_ReferenceSlot(le->slot);
01054            if (keyPtr) *keyPtr = key;
01055            break;
01056        }
01057     }
01058 
01059     SECITEM_FreeItem(keyID,PR_TRUE);
01060     PK11_FreeSlotList(list);
01061     return slot;
01062 
01063 }
01064 /*
01065  * import a cert for a private key we have already generated. Set the label
01066  * on both to be the nickname. This is for the Key Gen, orphaned key case.
01067  */
01068 PK11SlotInfo *
01069 PK11_KeyForDERCertExists(SECItem *derCert, CK_OBJECT_HANDLE *keyPtr, 
01070                                                         void *wincx) {
01071     CERTCertificate *cert;
01072     PK11SlotInfo *slot = NULL;
01073 
01074     /* letting this use go -- the only thing that the cert is used for is
01075      * to get the ID attribute.
01076      */
01077     cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
01078     if (cert == NULL) return NULL;
01079 
01080     slot = PK11_KeyForCertExists(cert, keyPtr, wincx);
01081     CERT_DestroyCertificate (cert);
01082     return slot;
01083 }
01084 
01085 PK11SlotInfo *
01086 PK11_ImportCertForKey(CERTCertificate *cert, char *nickname,void *wincx) {
01087     PK11SlotInfo *slot = NULL;
01088     CK_OBJECT_HANDLE key;
01089 
01090     slot = PK11_KeyForCertExists(cert,&key,wincx);
01091 
01092     if (slot) {
01093        if (PK11_ImportCert(slot,cert,key,nickname,PR_FALSE) != SECSuccess) {
01094            PK11_FreeSlot(slot);
01095            slot = NULL;
01096        }
01097     } else {
01098        PORT_SetError(SEC_ERROR_ADDING_CERT);
01099     }
01100 
01101     return slot;
01102 }
01103 
01104 PK11SlotInfo *
01105 PK11_ImportDERCertForKey(SECItem *derCert, char *nickname,void *wincx) {
01106     CERTCertificate *cert;
01107     PK11SlotInfo *slot = NULL;
01108 
01109     cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
01110                                    derCert, NULL, PR_FALSE, PR_TRUE);
01111     if (cert == NULL) return NULL;
01112 
01113     slot = PK11_ImportCertForKey(cert, nickname, wincx);
01114     CERT_DestroyCertificate (cert);
01115     return slot;
01116 }
01117 
01118 static CK_OBJECT_HANDLE
01119 pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, 
01120               CK_ATTRIBUTE *searchTemplate, int count, void *wincx) {
01121     PK11SlotList *list;
01122     PK11SlotListElement *le;
01123     CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE;
01124     PK11SlotInfo *slot = NULL;
01125     SECStatus rv;
01126 
01127     *slotPtr = NULL;
01128 
01129     /* get them all! */
01130     list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx);
01131     if (list == NULL) {
01132        return CK_INVALID_HANDLE;
01133     }
01134 
01135 
01136     /* Look for the slot that holds the Key */
01137     for (le = list->head ; le; le = le->next) {
01138        rv = pk11_AuthenticateUnfriendly(le->slot, PR_TRUE, wincx);
01139        if (rv != SECSuccess) continue;
01140 
01141        certHandle = pk11_FindObjectByTemplate(le->slot,searchTemplate,count);
01142        if (certHandle != CK_INVALID_HANDLE) {
01143            slot = PK11_ReferenceSlot(le->slot);
01144            break;
01145        }
01146     }
01147 
01148     PK11_FreeSlotList(list);
01149 
01150     if (slot == NULL) {
01151        return CK_INVALID_HANDLE;
01152     }
01153     *slotPtr = slot;
01154     return certHandle;
01155 }
01156 
01157 CERTCertificate *
01158 PK11_FindCertByIssuerAndSNOnToken(PK11SlotInfo *slot, 
01159                             CERTIssuerAndSN *issuerSN, void *wincx)
01160 {
01161     CERTCertificate *rvCert = NULL;
01162     NSSCertificate *cert = NULL;
01163     NSSDER issuer, serial;
01164     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
01165     NSSToken *token = slot->nssToken;
01166     nssSession *session;
01167     nssCryptokiObject *instance = NULL;
01168     nssPKIObject *object = NULL;
01169     SECItem *derSerial;
01170     PRStatus status;
01171 
01172     /* Paranoia */
01173     if (token == NULL) {
01174        PORT_SetError(SEC_ERROR_NO_TOKEN);
01175        return NULL;
01176     }
01177 
01178 
01179     /* PKCS#11 needs to use DER-encoded serial numbers.  Create a
01180      * CERTIssuerAndSN that actually has the encoded value and pass that
01181      * to PKCS#11 (and the crypto context).
01182      */
01183     derSerial = SEC_ASN1EncodeItem(NULL, NULL,
01184                                    &issuerSN->serialNumber,
01185                                    SEC_IntegerTemplate);
01186     if (!derSerial) {
01187        return NULL;
01188     }
01189 
01190     NSSITEM_FROM_SECITEM(&issuer, &issuerSN->derIssuer);
01191     NSSITEM_FROM_SECITEM(&serial, derSerial);
01192 
01193     session = nssToken_GetDefaultSession(token);
01194     if (!session) {
01195        goto loser;
01196     }
01197 
01198     instance = nssToken_FindCertificateByIssuerAndSerialNumber(token,session,
01199               &issuer, &serial, nssTokenSearchType_TokenForced, &status);
01200 
01201     SECITEM_FreeItem(derSerial, PR_TRUE);
01202 
01203     if (!instance) {
01204        goto loser;
01205     }
01206     object = nssPKIObject_Create(NULL, instance, td, NULL, nssPKIMonitor);
01207     if (!object) {
01208        goto loser;
01209     }
01210     instance = NULL; /* adopted by the previous call */
01211     cert = nssCertificate_Create(object);
01212     if (!cert) {
01213        goto loser;
01214     }
01215     object = NULL; /* adopted by the previous call */
01216     nssTrustDomain_AddCertsToCache(td, &cert,1);
01217     /* on failure, cert is freed below */
01218     rvCert = STAN_GetCERTCertificate(cert);
01219     if (!rvCert) {
01220        goto loser;
01221     }
01222     return rvCert;
01223 
01224 loser:
01225     if (instance) {
01226        nssCryptokiObject_Destroy(instance);
01227     }
01228     if (object) {
01229        nssPKIObject_Destroy(object);
01230     }
01231     if (cert) {
01232        nssCertificate_Destroy(cert);
01233     }
01234     return NULL;
01235 }
01236 
01237 /*
01238  * We're looking for a cert which we have the private key for that's on the
01239  * list of recipients. This searches one slot.
01240  * this is the new version for NSS SMIME code
01241  * this stuff should REALLY be in the SMIME code, but some things in here are not public
01242  * (they should be!)
01243  */
01244 static CERTCertificate *
01245 pk11_FindCertObjectByRecipientNew(PK11SlotInfo *slot, NSSCMSRecipient **recipientlist, int *rlIndex, void *pwarg)
01246 {
01247     NSSCMSRecipient *ri = NULL;
01248     int i;
01249 
01250     for (i=0; (ri = recipientlist[i]) != NULL; i++) {
01251        CERTCertificate *cert = NULL;
01252        if (ri->kind == RLSubjKeyID) {
01253            SECItem *derCert = cert_FindDERCertBySubjectKeyID(ri->id.subjectKeyID);
01254            if (derCert) {
01255               cert = PK11_FindCertFromDERCertItem(slot, derCert, pwarg);
01256               SECITEM_FreeItem(derCert, PR_TRUE);
01257            }
01258        } else {
01259            cert = PK11_FindCertByIssuerAndSNOnToken(slot, ri->id.issuerAndSN, 
01260                                                pwarg);
01261        }
01262        if (cert) {
01263            /* this isn't our cert */
01264            if ((cert->trust == NULL) ||
01265                      ((cert->trust->emailFlags & CERTDB_USER) != CERTDB_USER)) {
01266                CERT_DestroyCertificate(cert);
01267               continue;
01268            }
01269            ri->slot = PK11_ReferenceSlot(slot);
01270            *rlIndex = i;
01271            return cert;
01272        }
01273     }
01274     *rlIndex = -1;
01275     return NULL;
01276 }
01277 
01278 /*
01279  * This function is the same as above, but it searches all the slots.
01280  * this is the new version for NSS SMIME code
01281  * this stuff should REALLY be in the SMIME code, but some things in here are not public
01282  * (they should be!)
01283  */
01284 static CERTCertificate *
01285 pk11_AllFindCertObjectByRecipientNew(NSSCMSRecipient **recipientlist, void *wincx, int *rlIndex)
01286 {
01287     PK11SlotList *list;
01288     PK11SlotListElement *le;
01289     CERTCertificate *cert = NULL;
01290     SECStatus rv;
01291 
01292     /* get them all! */
01293     list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx);
01294     if (list == NULL) {
01295        return CK_INVALID_HANDLE;
01296     }
01297 
01298     /* Look for the slot that holds the Key */
01299     for (le = list->head ; le; le = le->next) {
01300        rv = pk11_AuthenticateUnfriendly(le->slot, PR_TRUE, wincx);
01301        if (rv != SECSuccess) continue;
01302 
01303        cert = pk11_FindCertObjectByRecipientNew(le->slot, 
01304                                    recipientlist, rlIndex, wincx);
01305        if (cert)
01306            break;
01307     }
01308 
01309     PK11_FreeSlotList(list);
01310 
01311     return cert;
01312 }
01313 
01314 /*
01315  * We're looking for a cert which we have the private key for that's on the
01316  * list of recipients. This searches one slot.
01317  */
01318 static CERTCertificate *
01319 pk11_FindCertObjectByRecipient(PK11SlotInfo *slot, 
01320        SEC_PKCS7RecipientInfo **recipientArray,
01321        SEC_PKCS7RecipientInfo **rip, void *pwarg)
01322 {
01323     SEC_PKCS7RecipientInfo *ri = NULL;
01324     int i;
01325 
01326     for (i=0; (ri = recipientArray[i]) != NULL; i++) {
01327        CERTCertificate *cert;
01328 
01329        cert = PK11_FindCertByIssuerAndSNOnToken(slot, ri->issuerAndSN, 
01330                                                         pwarg);
01331         if (cert) {
01332            /* this isn't our cert */
01333            if ((cert->trust == NULL) ||
01334                      ((cert->trust->emailFlags & CERTDB_USER) != CERTDB_USER)) {
01335                CERT_DestroyCertificate(cert);
01336               continue;
01337            }
01338            *rip = ri;
01339            return cert;
01340        }
01341 
01342     }
01343     *rip = NULL;
01344     return NULL;
01345 }
01346 
01347 /*
01348  * This function is the same as above, but it searches all the slots.
01349  */
01350 static CERTCertificate *
01351 pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, 
01352        SEC_PKCS7RecipientInfo **recipientArray,SEC_PKCS7RecipientInfo **rip,
01353                                                  void *wincx) {
01354     PK11SlotList *list;
01355     PK11SlotListElement *le;
01356     CERTCertificate * cert = NULL;
01357     PK11SlotInfo *slot = NULL;
01358     SECStatus rv;
01359 
01360     *slotPtr = NULL;
01361 
01362     /* get them all! */
01363     list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx);
01364     if (list == NULL) {
01365        return CK_INVALID_HANDLE;
01366     }
01367 
01368     *rip = NULL;
01369 
01370     /* Look for the slot that holds the Key */
01371     for (le = list->head ; le; le = le->next) {
01372        rv = pk11_AuthenticateUnfriendly(le->slot, PR_TRUE, wincx);
01373        if (rv != SECSuccess) continue;
01374 
01375        cert = pk11_FindCertObjectByRecipient(le->slot, recipientArray, 
01376                                                  rip, wincx);
01377        if (cert) {
01378            slot = PK11_ReferenceSlot(le->slot);
01379            break;
01380        }
01381     }
01382 
01383     PK11_FreeSlotList(list);
01384 
01385     if (slot == NULL) {
01386        return NULL;
01387     }
01388     *slotPtr = slot;
01389     PORT_Assert(cert != NULL);
01390     return cert;
01391 }
01392 
01393 /*
01394  * We need to invert the search logic for PKCS 7 because if we search for
01395  * each cert on the list over all the slots, we wind up with lots of spurious
01396  * password prompts. This way we get only one password prompt per slot, at
01397  * the max, and most of the time we can find the cert, and only prompt for
01398  * the key...
01399  */
01400 CERTCertificate *
01401 PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slotPtr, 
01402        SEC_PKCS7RecipientInfo **array, SEC_PKCS7RecipientInfo **rip,
01403                             SECKEYPrivateKey**privKey, void *wincx)
01404 {
01405     CERTCertificate *cert = NULL;
01406 
01407     *privKey = NULL;
01408     *slotPtr = NULL;
01409     cert = pk11_AllFindCertObjectByRecipient(slotPtr,array,rip,wincx);
01410     if (!cert) {
01411        return NULL;
01412     }
01413 
01414     *privKey = PK11_FindKeyByAnyCert(cert, wincx);
01415     if (*privKey == NULL) {
01416        goto loser;
01417     }
01418 
01419     return cert;
01420 loser:
01421     if (cert) CERT_DestroyCertificate(cert);
01422     if (*slotPtr) PK11_FreeSlot(*slotPtr);
01423     *slotPtr = NULL;
01424     return NULL;
01425 }
01426 
01427 static PRCallOnceType keyIDHashCallOnce;
01428 
01429 static PRStatus PR_CALLBACK
01430 pk11_keyIDHash_populate(void *wincx)
01431 {
01432     CERTCertList     *certList;
01433     CERTCertListNode *node = NULL;
01434     SECItem           subjKeyID = {siBuffer, NULL, 0};
01435 
01436     certList = PK11_ListCerts(PK11CertListUser, wincx);
01437     if (!certList) {
01438        return PR_FAILURE;
01439     }
01440 
01441     for (node = CERT_LIST_HEAD(certList);
01442          !CERT_LIST_END(node, certList);
01443          node = CERT_LIST_NEXT(node)) {
01444        if (CERT_FindSubjectKeyIDExtension(node->cert, 
01445                                           &subjKeyID) == SECSuccess && 
01446            subjKeyID.data != NULL) {
01447            cert_AddSubjectKeyIDMapping(&subjKeyID, node->cert);
01448            SECITEM_FreeItem(&subjKeyID, PR_FALSE);
01449        }
01450     }
01451     CERT_DestroyCertList(certList);
01452     return PR_SUCCESS;
01453 }
01454 
01455 /*
01456  * This is the new version of the above function for NSS SMIME code
01457  * this stuff should REALLY be in the SMIME code, but some things in here are not public
01458  * (they should be!)
01459  */
01460 int
01461 PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient **recipientlist, void *wincx)
01462 {
01463     CERTCertificate *cert;
01464     NSSCMSRecipient *rl;
01465     PRStatus rv;
01466     int rlIndex;
01467 
01468     rv = PR_CallOnceWithArg(&keyIDHashCallOnce, pk11_keyIDHash_populate, wincx);
01469     if (rv != PR_SUCCESS)
01470        return -1;
01471 
01472     cert = pk11_AllFindCertObjectByRecipientNew(recipientlist, wincx, &rlIndex);
01473     if (!cert) {
01474        return -1;
01475     }
01476 
01477     rl = recipientlist[rlIndex];
01478 
01479     /* at this point, rl->slot is set */
01480 
01481     rl->privkey = PK11_FindKeyByAnyCert(cert, wincx);
01482     if (rl->privkey == NULL) {
01483        goto loser;
01484     }
01485 
01486     /* make a cert from the cert handle */
01487     rl->cert = cert;
01488     return rlIndex;
01489 
01490 loser:
01491     if (cert) CERT_DestroyCertificate(cert);
01492     if (rl->slot) PK11_FreeSlot(rl->slot);
01493     rl->slot = NULL;
01494     return -1;
01495 }
01496 
01497 CERTCertificate *
01498 PK11_FindCertByIssuerAndSN(PK11SlotInfo **slotPtr, CERTIssuerAndSN *issuerSN,
01499                                                   void *wincx)
01500 {
01501     CERTCertificate *rvCert = NULL;
01502     NSSCertificate *cert;
01503     NSSDER issuer, serial;
01504     NSSCryptoContext *cc;
01505     SECItem *derSerial;
01506 
01507     if (slotPtr) *slotPtr = NULL;
01508 
01509     /* PKCS#11 needs to use DER-encoded serial numbers.  Create a
01510      * CERTIssuerAndSN that actually has the encoded value and pass that
01511      * to PKCS#11 (and the crypto context).
01512      */
01513     derSerial = SEC_ASN1EncodeItem(NULL, NULL,
01514                                    &issuerSN->serialNumber,
01515                                    SEC_IntegerTemplate);
01516     if (!derSerial) {
01517        return NULL;
01518     }
01519 
01520     NSSITEM_FROM_SECITEM(&issuer, &issuerSN->derIssuer);
01521     NSSITEM_FROM_SECITEM(&serial, derSerial);
01522 
01523     cc = STAN_GetDefaultCryptoContext();
01524     cert = NSSCryptoContext_FindCertificateByIssuerAndSerialNumber(cc, 
01525                                                                 &issuer, 
01526                                                                 &serial);
01527     if (cert) {
01528        SECITEM_FreeItem(derSerial, PR_TRUE);
01529        return STAN_GetCERTCertificateOrRelease(cert);
01530     }
01531 
01532     do {
01533        /* free the old cert on retry. Associated slot was not present */
01534        if (rvCert) {
01535            CERT_DestroyCertificate(rvCert);
01536            rvCert = NULL;
01537        }
01538 
01539        cert = NSSTrustDomain_FindCertificateByIssuerAndSerialNumber(
01540                                                   STAN_GetDefaultTrustDomain(),
01541                                                   &issuer,
01542                                                   &serial);
01543        if (!cert) {
01544            break;
01545        }
01546 
01547        rvCert = STAN_GetCERTCertificateOrRelease(cert);
01548        if (rvCert == NULL) {
01549           break;
01550        }
01551 
01552        /* Check to see if the cert's token is still there */
01553     } while (!PK11_IsPresent(rvCert->slot));
01554 
01555     if (rvCert && slotPtr) *slotPtr = PK11_ReferenceSlot(rvCert->slot);
01556 
01557     SECITEM_FreeItem(derSerial, PR_TRUE);
01558     return rvCert;
01559 }
01560 
01561 CK_OBJECT_HANDLE
01562 PK11_FindObjectForCert(CERTCertificate *cert, void *wincx, PK11SlotInfo **pSlot)
01563 {
01564     CK_OBJECT_HANDLE certHandle;
01565     CK_ATTRIBUTE searchTemplate    = { CKA_VALUE, NULL, 0 };
01566     
01567     PK11_SETATTRS(&searchTemplate, CKA_VALUE, cert->derCert.data,
01568                 cert->derCert.len);
01569 
01570     if (cert->slot) {
01571        certHandle = pk11_getcerthandle(cert->slot,cert,&searchTemplate,1);
01572        if (certHandle != CK_INVALID_HANDLE) {
01573            *pSlot = PK11_ReferenceSlot(cert->slot);
01574            return certHandle;
01575        }
01576     }
01577 
01578     certHandle = pk11_FindCertObjectByTemplate(pSlot,&searchTemplate,1,wincx);
01579     if (certHandle != CK_INVALID_HANDLE) {
01580        if (cert->slot == NULL) {
01581            cert->slot = PK11_ReferenceSlot(*pSlot);
01582            cert->pkcs11ID = certHandle;
01583            cert->ownSlot = PR_TRUE;
01584            cert->series = cert->slot->series;
01585        }
01586     }
01587 
01588     return(certHandle);
01589 }
01590 
01591 SECKEYPrivateKey *
01592 PK11_FindKeyByAnyCert(CERTCertificate *cert, void *wincx)
01593 {
01594     CK_OBJECT_HANDLE certHandle;
01595     CK_OBJECT_HANDLE keyHandle;
01596     PK11SlotInfo *slot = NULL;
01597     SECKEYPrivateKey *privKey = NULL;
01598     PRBool needLogin;
01599     SECStatus rv;
01600     int err;
01601 
01602     certHandle = PK11_FindObjectForCert(cert, wincx, &slot);
01603     if (certHandle == CK_INVALID_HANDLE) {
01604         return NULL;
01605     }
01606     /*
01607      * prevent a login race condition. If slot is logged in between
01608      * our call to pk11_LoginStillRequired and the 
01609      * PK11_MatchItem. The matchItem call will either succeed, or
01610      * we will call it one more time after calling PK11_Authenticate 
01611      * (which is a noop on an authenticated token).
01612      */
01613     needLogin = pk11_LoginStillRequired(slot,wincx);
01614     keyHandle = PK11_MatchItem(slot,certHandle,CKO_PRIVATE_KEY);
01615     if ((keyHandle == CK_INVALID_HANDLE) &&  needLogin &&
01616                      (SSL_ERROR_NO_CERTIFICATE == (err = PORT_GetError()) ||
01617                       SEC_ERROR_TOKEN_NOT_LOGGED_IN == err ) ) {
01618        /* authenticate and try again */
01619        rv = PK11_Authenticate(slot, PR_TRUE, wincx);
01620        if (rv == SECSuccess) {
01621             keyHandle = PK11_MatchItem(slot,certHandle,CKO_PRIVATE_KEY);
01622        }
01623     }
01624     if (keyHandle != CK_INVALID_HANDLE) { 
01625         privKey =  PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx);
01626     }
01627     if (slot) {
01628        PK11_FreeSlot(slot);
01629     }
01630     return privKey;
01631 }
01632 
01633 CK_OBJECT_HANDLE
01634 pk11_FindPubKeyByAnyCert(CERTCertificate *cert, PK11SlotInfo **slot, void *wincx)
01635 {
01636     CK_OBJECT_HANDLE certHandle;
01637     CK_OBJECT_HANDLE keyHandle;
01638 
01639     certHandle = PK11_FindObjectForCert(cert, wincx, slot);
01640     if (certHandle == CK_INVALID_HANDLE) {
01641         return CK_INVALID_HANDLE;
01642     }
01643     keyHandle = PK11_MatchItem(*slot,certHandle,CKO_PUBLIC_KEY);
01644     if (keyHandle == CK_INVALID_HANDLE) { 
01645        PK11_FreeSlot(*slot);
01646        return CK_INVALID_HANDLE;
01647     }
01648     return keyHandle;
01649 }
01650 
01651 /*
01652  * find the number of certs in the slot with the same subject name
01653  */
01654 int
01655 PK11_NumberCertsForCertSubject(CERTCertificate *cert)
01656 {
01657     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
01658     CK_ATTRIBUTE theTemplate[] = {
01659        { CKA_CLASS, NULL, 0 },
01660        { CKA_SUBJECT, NULL, 0 },
01661     };
01662     CK_ATTRIBUTE *attr = theTemplate;
01663    int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]);
01664 
01665     PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++;
01666     PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len);
01667 
01668     if (cert->slot == NULL) {
01669        PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
01670                                                  PR_FALSE,PR_TRUE,NULL);
01671        PK11SlotListElement *le;
01672        int count = 0;
01673 
01674        /* loop through all the fortezza tokens */
01675        for (le = list->head; le; le = le->next) {
01676            count += PK11_NumberObjectsFor(le->slot,theTemplate,templateSize);
01677        }
01678        PK11_FreeSlotList(list);
01679        return count;
01680     }
01681 
01682     return PK11_NumberObjectsFor(cert->slot,theTemplate,templateSize);
01683 }
01684 
01685 /*
01686  *  Walk all the certs with the same subject
01687  */
01688 SECStatus
01689 PK11_TraverseCertsForSubject(CERTCertificate *cert,
01690         SECStatus(* callback)(CERTCertificate*, void *), void *arg)
01691 {
01692     if(!cert) {
01693        return SECFailure;
01694     }
01695     if (cert->slot == NULL) {
01696        PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
01697                                                  PR_FALSE,PR_TRUE,NULL);
01698        PK11SlotListElement *le;
01699 
01700        /* loop through all the tokens */
01701        for (le = list->head; le; le = le->next) {
01702            PK11_TraverseCertsForSubjectInSlot(cert,le->slot,callback,arg);
01703        }
01704        PK11_FreeSlotList(list);
01705        return SECSuccess;
01706 
01707     }
01708 
01709     return PK11_TraverseCertsForSubjectInSlot(cert, cert->slot, callback, arg);
01710 }
01711 
01712 SECStatus
01713 PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot,
01714        SECStatus(* callback)(CERTCertificate*, void *), void *arg)
01715 {
01716     PRStatus nssrv = PR_SUCCESS;
01717     NSSToken *token;
01718     NSSDER subject;
01719     NSSTrustDomain *td;
01720     nssList *subjectList;
01721     nssPKIObjectCollection *collection;
01722     nssCryptokiObject **instances;
01723     NSSCertificate **certs;
01724     nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
01725     td = STAN_GetDefaultTrustDomain();
01726     NSSITEM_FROM_SECITEM(&subject, &cert->derSubject);
01727     token = PK11Slot_GetNSSToken(slot);
01728     if (!nssToken_IsPresent(token)) {
01729        return SECSuccess;
01730     }
01731     collection = nssCertificateCollection_Create(td, NULL);
01732     if (!collection) {
01733        return SECFailure;
01734     }
01735     subjectList = nssList_Create(NULL, PR_FALSE);
01736     if (!subjectList) {
01737        nssPKIObjectCollection_Destroy(collection);
01738        return SECFailure;
01739     }
01740     (void)nssTrustDomain_GetCertsForSubjectFromCache(td, &subject, 
01741                                                      subjectList);
01742     transfer_token_certs_to_collection(subjectList, token, collection);
01743     instances = nssToken_FindCertificatesBySubject(token, NULL,
01744                                                   &subject, 
01745                                                   tokenOnly, 0, &nssrv);
01746     nssPKIObjectCollection_AddInstances(collection, instances, 0);
01747     nss_ZFreeIf(instances);
01748     nssList_Destroy(subjectList);
01749     certs = nssPKIObjectCollection_GetCertificates(collection,
01750                                                    NULL, 0, NULL);
01751     nssPKIObjectCollection_Destroy(collection);
01752     if (certs) {
01753        CERTCertificate *oldie;
01754        NSSCertificate **cp;
01755        for (cp = certs; *cp; cp++) {
01756            oldie = STAN_GetCERTCertificate(*cp);
01757            if (!oldie) {
01758               continue;
01759            }
01760            if ((*callback)(oldie, arg) != SECSuccess) {
01761               nssrv = PR_FAILURE;
01762               break;
01763            }
01764        }
01765        nssCertificateArray_Destroy(certs);
01766     }
01767     return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
01768 }
01769 
01770 SECStatus
01771 PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot,
01772        SECStatus(* callback)(CERTCertificate*, void *), void *arg)
01773 {
01774     struct nss3_cert_cbstr pk11cb;
01775     PRStatus nssrv = PR_SUCCESS;
01776     NSSToken *token;
01777     NSSTrustDomain *td;
01778     NSSUTF8 *nick;
01779     PRBool created = PR_FALSE;
01780     nssCryptokiObject **instances;
01781     nssPKIObjectCollection *collection = NULL;
01782     NSSCertificate **certs;
01783     nssList *nameList = NULL;
01784     nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
01785     pk11cb.callback = callback;
01786     pk11cb.arg = arg;
01787     token = PK11Slot_GetNSSToken(slot);
01788     if (!nssToken_IsPresent(token)) {
01789        return SECSuccess;
01790     }
01791     if (nickname->data[nickname->len-1] != '\0') {
01792        nick = nssUTF8_Create(NULL, nssStringType_UTF8String, 
01793                              nickname->data, nickname->len);
01794        created = PR_TRUE;
01795     } else {
01796        nick = (NSSUTF8 *)nickname->data;
01797     }
01798     td = STAN_GetDefaultTrustDomain();
01799     collection = nssCertificateCollection_Create(td, NULL);
01800     if (!collection) {
01801        goto loser;
01802     }
01803     nameList = nssList_Create(NULL, PR_FALSE);
01804     if (!nameList) {
01805        goto loser;
01806     }
01807     (void)nssTrustDomain_GetCertsForNicknameFromCache(td, nick, nameList);
01808     transfer_token_certs_to_collection(nameList, token, collection);
01809     instances = nssToken_FindCertificatesByNickname(token, NULL,
01810                                                    nick,
01811                                                    tokenOnly, 0, &nssrv);
01812     nssPKIObjectCollection_AddInstances(collection, instances, 0);
01813     nss_ZFreeIf(instances);
01814     nssList_Destroy(nameList);
01815     certs = nssPKIObjectCollection_GetCertificates(collection,
01816                                                    NULL, 0, NULL);
01817     nssPKIObjectCollection_Destroy(collection);
01818     if (certs) {
01819        CERTCertificate *oldie;
01820        NSSCertificate **cp;
01821        for (cp = certs; *cp; cp++) {
01822            oldie = STAN_GetCERTCertificate(*cp);
01823            if (!oldie) {
01824               continue;
01825            }
01826            if ((*callback)(oldie, arg) != SECSuccess) {
01827               nssrv = PR_FAILURE;
01828               break;
01829            }
01830        }
01831        nssCertificateArray_Destroy(certs);
01832     }
01833     if (created) nss_ZFreeIf(nick);
01834     return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
01835 loser:
01836     if (created) {
01837        nss_ZFreeIf(nick);
01838     }
01839     if (collection) {
01840        nssPKIObjectCollection_Destroy(collection);
01841     }
01842     if (nameList) {
01843        nssList_Destroy(nameList);
01844     }
01845     return SECFailure;
01846 }
01847 
01848 SECStatus
01849 PK11_TraverseCertsInSlot(PK11SlotInfo *slot,
01850        SECStatus(* callback)(CERTCertificate*, void *), void *arg)
01851 {
01852     PRStatus nssrv;
01853     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
01854     NSSToken *tok;
01855     nssList *certList = NULL;
01856     nssCryptokiObject **instances;
01857     nssPKIObjectCollection *collection;
01858     NSSCertificate **certs;
01859     nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
01860     tok = PK11Slot_GetNSSToken(slot);
01861     if (!nssToken_IsPresent(tok)) {
01862        return SECSuccess;
01863     }
01864     collection = nssCertificateCollection_Create(td, NULL);
01865     if (!collection) {
01866        return SECFailure;
01867     }
01868     certList = nssList_Create(NULL, PR_FALSE);
01869     if (!certList) {
01870        nssPKIObjectCollection_Destroy(collection);
01871        return SECFailure;
01872     }
01873     (void *)nssTrustDomain_GetCertsFromCache(td, certList);
01874     transfer_token_certs_to_collection(certList, tok, collection);
01875     instances = nssToken_FindCertificates(tok, NULL,
01876                                           tokenOnly, 0, &nssrv);
01877     nssPKIObjectCollection_AddInstances(collection, instances, 0);
01878     nss_ZFreeIf(instances);
01879     nssList_Destroy(certList);
01880     certs = nssPKIObjectCollection_GetCertificates(collection,
01881                                                    NULL, 0, NULL);
01882     nssPKIObjectCollection_Destroy(collection);
01883     if (certs) {
01884        CERTCertificate *oldie;
01885        NSSCertificate **cp;
01886        for (cp = certs; *cp; cp++) {
01887            oldie = STAN_GetCERTCertificate(*cp);
01888            if (!oldie) {
01889               continue;
01890            }
01891            if ((*callback)(oldie, arg) != SECSuccess) {
01892               nssrv = PR_FAILURE;
01893               break;
01894            }
01895        }
01896        nssCertificateArray_Destroy(certs);
01897     }
01898     return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
01899 }
01900 
01901 /*
01902  * return the certificate associated with a derCert 
01903  */
01904 CERTCertificate *
01905 PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert,
01906                                                          void *wincx)
01907 {
01908     return PK11_FindCertFromDERCertItem(slot, &cert->derCert, wincx);
01909 }
01910 
01911 CERTCertificate *
01912 PK11_FindCertFromDERCertItem(PK11SlotInfo *slot, SECItem *inDerCert,
01913                                                          void *wincx)
01914 
01915 {
01916     NSSCertificate *c;
01917     NSSDER derCert;
01918     NSSToken *tok;
01919     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
01920     SECStatus rv;
01921 
01922     tok = PK11Slot_GetNSSToken(slot);
01923     NSSITEM_FROM_SECITEM(&derCert, inDerCert);
01924     rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx);
01925     if (rv != SECSuccess) {
01926        PK11_FreeSlot(slot);
01927        return NULL;
01928     }
01929     c = NSSTrustDomain_FindCertificateByEncodedCertificate(td, &derCert);
01930     if (c) {
01931        PRBool isToken = PR_FALSE;
01932        NSSToken **tp;
01933        NSSToken **tokens = nssPKIObject_GetTokens(&c->object, NULL);
01934        if (tokens) {
01935            for (tp = tokens; *tp; tp++) {
01936               if (*tp == tok) {
01937                   isToken = PR_TRUE;
01938                   break;
01939               }
01940            }
01941            if (!isToken) {
01942               NSSCertificate_Destroy(c);
01943               c = NULL;
01944            }
01945            nssTokenArray_Destroy(tokens);
01946        }
01947     }
01948     return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
01949 } 
01950 
01951 /* mcgreer 3.4 -- nobody uses this, ignoring */
01952 /*
01953  * return the certificate associated with a derCert 
01954  */
01955 CERTCertificate *
01956 PK11_FindCertFromDERSubjectAndNickname(PK11SlotInfo *slot, 
01957                                    CERTCertificate *cert, 
01958                                    char *nickname, void *wincx)
01959 {
01960     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
01961     CK_ATTRIBUTE theTemplate[] = {
01962        { CKA_SUBJECT, NULL, 0 },
01963        { CKA_LABEL, NULL, 0 },
01964        { CKA_CLASS, NULL, 0 }
01965     };
01966     /* if you change the array, change the variable below as well */
01967     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
01968     CK_OBJECT_HANDLE certh;
01969     CK_ATTRIBUTE *attrs = theTemplate;
01970     SECStatus rv;
01971 
01972     PK11_SETATTRS(attrs, CKA_SUBJECT, cert->derSubject.data, 
01973                                           cert->derSubject.len); attrs++;
01974     PK11_SETATTRS(attrs, CKA_LABEL, nickname, PORT_Strlen(nickname));
01975     PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass));
01976 
01977     /*
01978      * issue the find
01979      */
01980     rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx);
01981     if (rv != SECSuccess) return NULL;
01982 
01983     certh = pk11_getcerthandle(slot,cert,theTemplate,tsize);
01984     if (certh == CK_INVALID_HANDLE) {
01985        return NULL;
01986     }
01987 
01988     return PK11_MakeCertFromHandle(slot, certh, NULL);
01989 }
01990 
01991 /*
01992  * import a cert for a private key we have already generated. Set the label
01993  * on both to be the nickname.
01994  */
01995 static CK_OBJECT_HANDLE 
01996 pk11_findKeyObjectByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, 
01997                                                         void *wincx)
01998 {
01999     SECItem *keyID;
02000     CK_OBJECT_HANDLE key;
02001     SECStatus rv;
02002     PRBool needLogin;
02003     int err;
02004 
02005     if((slot == NULL) || (cert == NULL)) {
02006        return CK_INVALID_HANDLE;
02007     }
02008 
02009     keyID = pk11_mkcertKeyID(cert);
02010     if(keyID == NULL) {
02011        return CK_INVALID_HANDLE;
02012     }
02013 
02014     /*
02015      * prevent a login race condition. If slot is logged in between
02016      * our call to pk11_LoginStillRequired and the 
02017      * pk11_FindPrivateKeyFromCerID. The matchItem call will either succeed, or
02018      * we will call it one more time after calling PK11_Authenticate 
02019      * (which is a noop on an authenticated token).
02020      */
02021     needLogin = pk11_LoginStillRequired(slot,wincx);
02022     key = pk11_FindPrivateKeyFromCertID(slot, keyID);
02023     if ((key == CK_INVALID_HANDLE) && needLogin &&
02024                      (SSL_ERROR_NO_CERTIFICATE == (err = PORT_GetError()) ||
02025                       SEC_ERROR_TOKEN_NOT_LOGGED_IN == err )) {
02026        /* authenticate and try again */
02027        rv = PK11_Authenticate(slot, PR_TRUE, wincx);
02028        if (rv != SECSuccess) goto loser;
02029        key = pk11_FindPrivateKeyFromCertID(slot, keyID);
02030    }
02031 
02032 loser:
02033     SECITEM_ZfreeItem(keyID, PR_TRUE);
02034     return key;
02035 }
02036 
02037 SECKEYPrivateKey *
02038 PK11_FindKeyByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, 
02039                                                         void *wincx)
02040 {
02041     CK_OBJECT_HANDLE keyHandle;
02042 
02043     if((slot == NULL) || (cert == NULL)) {
02044        return NULL;
02045     }
02046 
02047     keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx);
02048     if (keyHandle == CK_INVALID_HANDLE) {
02049        return NULL;
02050     }
02051 
02052     return PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,wincx);
02053 }
02054 
02055 SECStatus
02056 PK11_ImportCertForKeyToSlot(PK11SlotInfo *slot, CERTCertificate *cert, 
02057                                           char *nickname, 
02058                                           PRBool addCertUsage,void *wincx)
02059 {
02060     CK_OBJECT_HANDLE keyHandle;
02061 
02062     if((slot == NULL) || (cert == NULL) || (nickname == NULL)) {
02063        return SECFailure;
02064     }
02065 
02066     keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx);
02067     if (keyHandle == CK_INVALID_HANDLE) {
02068        return SECFailure;
02069     }
02070 
02071     return PK11_ImportCert(slot, cert, keyHandle, nickname, addCertUsage);
02072 }   
02073 
02074 
02075 /* remove when the real version comes out */
02076 #define SEC_OID_MISSI_KEA 300  /* until we have v3 stuff merged */
02077 PRBool
02078 KEAPQGCompare(CERTCertificate *server,CERTCertificate *cert) {
02079 
02080     if ( SECKEY_KEAParamCompare(server,cert) == SECEqual ) {
02081         return PR_TRUE;
02082     } else {
02083        return PR_FALSE;
02084     }
02085 }
02086 
02087 PRBool
02088 PK11_FortezzaHasKEA(CERTCertificate *cert) {
02089    /* look at the subject and see if it is a KEA for MISSI key */
02090    SECOidData *oid;
02091 
02092    if ((cert->trust == NULL) ||
02093        ((cert->trust->sslFlags & CERTDB_USER) != CERTDB_USER)) {
02094        return PR_FALSE;
02095    }
02096 
02097    oid = SECOID_FindOID(&cert->subjectPublicKeyInfo.algorithm.algorithm);
02098 
02099 
02100    return (PRBool)((oid->offset == SEC_OID_MISSI_KEA_DSS_OLD) || 
02101               (oid->offset == SEC_OID_MISSI_KEA_DSS) ||
02102                             (oid->offset == SEC_OID_MISSI_KEA)) ;
02103 }
02104 
02105 /*
02106  * Find a kea cert on this slot that matches the domain of it's peer
02107  */
02108 static CERTCertificate
02109 *pk11_GetKEAMate(PK11SlotInfo *slot,CERTCertificate *peer)
02110 {
02111     int i;
02112     CERTCertificate *returnedCert = NULL;
02113 
02114     for (i=0; i < slot->cert_count; i++) {
02115        CERTCertificate *cert = slot->cert_array[i];
02116 
02117        if (PK11_FortezzaHasKEA(cert) && KEAPQGCompare(peer,cert)) {
02118               returnedCert = CERT_DupCertificate(cert);
02119               break;
02120        }
02121     }
02122     return returnedCert;
02123 }
02124 
02125 /*
02126  * The following is a FORTEZZA only Certificate request. We call this when we
02127  * are doing a non-client auth SSL connection. We are only interested in the
02128  * fortezza slots, and we are only interested in certs that share the same root
02129  * key as the server.
02130  */
02131 CERTCertificate *
02132 PK11_FindBestKEAMatch(CERTCertificate *server, void *wincx)
02133 {
02134     PK11SlotList *keaList = PK11_GetAllTokens(CKM_KEA_KEY_DERIVE,
02135                                                  PR_FALSE,PR_TRUE,wincx);
02136     PK11SlotListElement *le;
02137     CERTCertificate *returnedCert = NULL;
02138     SECStatus rv;
02139 
02140     /* loop through all the fortezza tokens */
02141     for (le = keaList->head; le; le = le->next) {
02142         rv = PK11_Authenticate(le->slot, PR_TRUE, wincx);
02143         if (rv != SECSuccess) continue;
02144        if (le->slot->session == CK_INVALID_SESSION) {
02145            continue;
02146        }
02147        returnedCert = pk11_GetKEAMate(le->slot,server);
02148        if (returnedCert) break;
02149     }
02150     PK11_FreeSlotList(keaList);
02151 
02152     return returnedCert;
02153 }
02154 
02155 /*
02156  * find a matched pair of kea certs to key exchange parameters from one 
02157  * fortezza card to another as necessary.
02158  */
02159 SECStatus
02160 PK11_GetKEAMatchedCerts(PK11SlotInfo *slot1, PK11SlotInfo *slot2,
02161        CERTCertificate **cert1, CERTCertificate **cert2)
02162 {
02163     CERTCertificate *returnedCert = NULL;
02164     int i;
02165 
02166     for (i=0; i < slot1->cert_count; i++) {
02167        CERTCertificate *cert = slot1->cert_array[i];
02168 
02169        if (PK11_FortezzaHasKEA(cert)) {
02170            returnedCert = pk11_GetKEAMate(slot2,cert);
02171            if (returnedCert != NULL) {
02172               *cert2 = returnedCert;
02173               *cert1 = CERT_DupCertificate(cert);
02174               return SECSuccess;
02175            }
02176        }
02177     }
02178     return SECFailure;
02179 }
02180 
02181 /*
02182  * return the private key From a given Cert
02183  */
02184 CK_OBJECT_HANDLE
02185 PK11_FindCertInSlot(PK11SlotInfo *slot, CERTCertificate *cert, void *wincx)
02186 {
02187     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
02188     CK_ATTRIBUTE theTemplate[] = {
02189        { CKA_VALUE, NULL, 0 },
02190        { CKA_CLASS, NULL, 0 }
02191     };
02192     /* if you change the array, change the variable below as well */
02193     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
02194     CK_ATTRIBUTE *attrs = theTemplate;
02195     SECStatus rv;
02196 
02197     PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data,
02198                                           cert->derCert.len); attrs++;
02199     PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass));
02200 
02201     /*
02202      * issue the find
02203      */
02204     rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx);
02205     if (rv != SECSuccess) {
02206        return CK_INVALID_HANDLE;
02207     }
02208 
02209     return pk11_getcerthandle(slot,cert,theTemplate,tsize);
02210 }
02211 
02212 SECItem *
02213 PK11_GetKeyIDFromCert(CERTCertificate *cert, void *wincx)
02214 {
02215     CK_OBJECT_HANDLE handle;
02216     PK11SlotInfo *slot = NULL;
02217     CK_ATTRIBUTE theTemplate[] = {
02218        { CKA_ID, NULL, 0 },
02219     };
02220     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
02221     SECItem *item = NULL;
02222     CK_RV crv;
02223 
02224     handle = PK11_FindObjectForCert(cert,wincx,&slot);
02225     if (handle == CK_INVALID_HANDLE) {
02226        goto loser;
02227     }
02228 
02229     crv = PK11_GetAttributes(NULL,slot,handle,theTemplate,tsize);
02230     if (crv != CKR_OK) {
02231        PORT_SetError( PK11_MapError(crv) );
02232        goto loser;
02233     }
02234 
02235     item = PORT_ZNew(SECItem);
02236     if (item) {
02237         item->data = (unsigned char*) theTemplate[0].pValue;
02238         item->len = theTemplate[0].ulValueLen;
02239     }
02240 
02241 loser:
02242     PK11_FreeSlot(slot);
02243     return item;
02244 }
02245 
02246 struct listCertsStr {
02247     PK11CertListType type;
02248     CERTCertList *certList;
02249 };
02250 
02251 static PRStatus
02252 pk11ListCertCallback(NSSCertificate *c, void *arg)
02253 {
02254     struct listCertsStr *listCertP = (struct listCertsStr *)arg;
02255     CERTCertificate *newCert = NULL;
02256     PK11CertListType type = listCertP->type;
02257     CERTCertList *certList = listCertP->certList;
02258     PRBool isUnique = PR_FALSE;
02259     PRBool isCA = PR_FALSE;
02260     char *nickname = NULL;
02261     unsigned int certType;
02262 
02263     if ((type == PK11CertListUnique) || (type == PK11CertListRootUnique) ||
02264         (type == PK11CertListCAUnique) || (type == PK11CertListUserUnique) ) {
02265         /* only list one instance of each certificate, even if several exist */
02266        isUnique = PR_TRUE;
02267     }
02268     if ((type == PK11CertListCA) || (type == PK11CertListRootUnique) ||
02269         (type == PK11CertListCAUnique)) {
02270        isCA = PR_TRUE;
02271     }
02272 
02273     /* if we want user certs and we don't have one skip this cert */
02274     if ( ( (type == PK11CertListUser) || (type == PK11CertListUserUnique) ) && 
02275               !NSSCertificate_IsPrivateKeyAvailable(c, NULL,NULL)) {
02276        return PR_SUCCESS;
02277     }
02278 
02279     /* PK11CertListRootUnique means we want CA certs without a private key.
02280      * This is for legacy app support . PK11CertListCAUnique should be used
02281      * instead to get all CA certs, regardless of private key
02282      */
02283     if ((type == PK11CertListRootUnique) && 
02284               NSSCertificate_IsPrivateKeyAvailable(c, NULL,NULL)) {
02285        return PR_SUCCESS;
02286     }
02287 
02288     /* caller still owns the reference to 'c' */
02289     newCert = STAN_GetCERTCertificate(c);
02290     if (!newCert) {
02291        return PR_SUCCESS;
02292     }
02293     /* if we want CA certs and it ain't one, skip it */
02294     if( isCA  && (!CERT_IsCACert(newCert, &certType)) ) {
02295        return PR_SUCCESS;
02296     }
02297     if (isUnique) {
02298        CERT_DupCertificate(newCert);
02299 
02300        nickname = STAN_GetCERTCertificateName(certList->arena, c);
02301 
02302        /* put slot certs at the end */
02303        if (newCert->slot && !PK11_IsInternal(newCert->slot)) {
02304            CERT_AddCertToListTailWithData(certList,newCert,nickname);
02305        } else {
02306            CERT_AddCertToListHeadWithData(certList,newCert,nickname);
02307        }
02308     } else {
02309        /* add multiple instances to the cert list */
02310        nssCryptokiObject **ip;
02311        nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
02312        if (!instances) {
02313            return PR_SUCCESS;
02314        }
02315        for (ip = instances; *ip; ip++) {
02316            nssCryptokiObject *instance = *ip;
02317            PK11SlotInfo *slot = instance->token->pk11slot;
02318 
02319            /* put the same CERTCertificate in the list for all instances */
02320            CERT_DupCertificate(newCert);
02321 
02322            nickname = STAN_GetCERTCertificateNameForInstance(
02323                      certList->arena, c, instance);
02324 
02325            /* put slot certs at the end */
02326            if (slot && !PK11_IsInternal(slot)) {
02327               CERT_AddCertToListTailWithData(certList,newCert,nickname);
02328            } else {
02329               CERT_AddCertToListHeadWithData(certList,newCert,nickname);
02330            }
02331        }
02332        nssCryptokiObjectArray_Destroy(instances);
02333     }
02334     return PR_SUCCESS;
02335 }
02336 
02337 
02338 CERTCertList *
02339 PK11_ListCerts(PK11CertListType type, void *pwarg)
02340 {
02341     NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain();
02342     CERTCertList *certList = NULL;
02343     struct listCertsStr listCerts;
02344     certList = CERT_NewCertList();
02345     listCerts.type = type;
02346     listCerts.certList = certList;
02347 
02348     /* authenticate to the slots */
02349     (void) pk11_TraverseAllSlots( NULL, NULL, PR_TRUE, pwarg);
02350     NSSTrustDomain_TraverseCertificates(defaultTD, pk11ListCertCallback,
02351                                                          &listCerts);
02352     return certList;
02353 }
02354     
02355 SECItem *
02356 PK11_GetLowLevelKeyIDForCert(PK11SlotInfo *slot,
02357                                    CERTCertificate *cert, void *wincx)
02358 {
02359     CK_ATTRIBUTE theTemplate[] = {
02360        { CKA_VALUE, NULL, 0 },
02361        { CKA_CLASS, NULL, 0 }
02362     };
02363     /* if you change the array, change the variable below as well */
02364     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
02365     CK_OBJECT_HANDLE certHandle;
02366     CK_ATTRIBUTE *attrs = theTemplate;
02367     PK11SlotInfo *slotRef = NULL;
02368     SECItem *item;
02369     SECStatus rv;
02370 
02371     if (slot) {
02372        PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, 
02373                                           cert->derCert.len); attrs++;
02374  
02375        rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx);
02376        if (rv != SECSuccess) {
02377            return NULL;
02378        }
02379         certHandle = pk11_getcerthandle(slot,cert,theTemplate,tsize);
02380     } else {
02381        certHandle = PK11_FindObjectForCert(cert, wincx, &slotRef);
02382        if (certHandle == CK_INVALID_HANDLE) {
02383           return pk11_mkcertKeyID(cert);
02384        }
02385        slot = slotRef;
02386     }
02387 
02388     if (certHandle == CK_INVALID_HANDLE) {
02389         return NULL;
02390     }
02391 
02392     item = pk11_GetLowLevelKeyFromHandle(slot,certHandle);
02393     if (slotRef) PK11_FreeSlot(slotRef);
02394     return item;
02395 }
02396 
02397 /* argument type for listCertsCallback */
02398 typedef struct {
02399     CERTCertList *list;
02400     PK11SlotInfo *slot;
02401 } ListCertsArg;
02402 
02403 static SECStatus
02404 listCertsCallback(CERTCertificate* cert, void*arg)
02405 {
02406     ListCertsArg *cdata = (ListCertsArg*)arg;
02407     char *nickname = NULL;
02408     nssCryptokiObject *instance, **ci;
02409     nssCryptokiObject **instances;
02410     NSSCertificate *c = STAN_GetNSSCertificate(cert);
02411 
02412     instances = nssPKIObject_GetInstances(&c->object);
02413     if (!instances) {
02414         return SECFailure;
02415     }
02416     instance = NULL;
02417     for (ci = instances; *ci; ci++) {
02418        if ((*ci)->token->pk11slot == cdata->slot) {
02419            instance = *ci;
02420            break;
02421        }
02422     }
02423     PORT_Assert(instance != NULL);
02424     if (!instance) {
02425        nssCryptokiObjectArray_Destroy(instances);
02426        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
02427        return SECFailure;
02428     }
02429     nickname = STAN_GetCERTCertificateNameForInstance(cdata->list->arena,
02430        c, instance);
02431     nssCryptokiObjectArray_Destroy(instances);
02432 
02433     return CERT_AddCertToListTailWithData(cdata->list, 
02434                             CERT_DupCertificate(cert),nickname);
02435 }
02436 
02437 CERTCertList *
02438 PK11_ListCertsInSlot(PK11SlotInfo *slot)
02439 {
02440     SECStatus status;
02441     CERTCertList *certs;
02442     ListCertsArg cdata;
02443 
02444     certs = CERT_NewCertList();
02445     if(certs == NULL) return NULL;
02446     cdata.list = certs;
02447     cdata.slot = slot;
02448 
02449     status = PK11_TraverseCertsInSlot(slot, listCertsCallback,
02450               &cdata);
02451 
02452     if( status != SECSuccess ) {
02453        CERT_DestroyCertList(certs);
02454        certs = NULL;
02455     }
02456 
02457     return certs;
02458 }
02459