1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pk11wrap/pk11cert.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2691 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * This file manages PKCS #11 instances of certificates. 1.9 + */ 1.10 + 1.11 +#include "secport.h" 1.12 +#include "seccomon.h" 1.13 +#include "secmod.h" 1.14 +#include "secmodi.h" 1.15 +#include "secmodti.h" 1.16 +#include "pkcs11.h" 1.17 +#include "pk11func.h" 1.18 +#include "cert.h" 1.19 +#include "certi.h" 1.20 +#include "secitem.h" 1.21 +#include "key.h" 1.22 +#include "secoid.h" 1.23 +#include "pkcs7t.h" 1.24 +#include "cmsreclist.h" 1.25 + 1.26 +#include "certdb.h" 1.27 +#include "secerr.h" 1.28 +#include "sslerr.h" 1.29 + 1.30 +#include "pki3hack.h" 1.31 +#include "dev3hack.h" 1.32 + 1.33 +#include "devm.h" 1.34 +#include "nsspki.h" 1.35 +#include "pki.h" 1.36 +#include "pkim.h" 1.37 +#include "pkitm.h" 1.38 +#include "pkistore.h" /* to remove temp cert */ 1.39 +#include "devt.h" 1.40 + 1.41 +extern const NSSError NSS_ERROR_NOT_FOUND; 1.42 +extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; 1.43 + 1.44 +struct nss3_cert_cbstr { 1.45 + SECStatus(* callback)(CERTCertificate*, void *); 1.46 + nssList *cached; 1.47 + void *arg; 1.48 +}; 1.49 + 1.50 +/* Translate from NSSCertificate to CERTCertificate, then pass the latter 1.51 + * to a callback. 1.52 + */ 1.53 +static PRStatus convert_cert(NSSCertificate *c, void *arg) 1.54 +{ 1.55 + CERTCertificate *nss3cert; 1.56 + SECStatus secrv; 1.57 + struct nss3_cert_cbstr *nss3cb = (struct nss3_cert_cbstr *)arg; 1.58 + /* 'c' is not adopted. caller will free it */ 1.59 + nss3cert = STAN_GetCERTCertificate(c); 1.60 + if (!nss3cert) return PR_FAILURE; 1.61 + secrv = (*nss3cb->callback)(nss3cert, nss3cb->arg); 1.62 + return (secrv) ? PR_FAILURE : PR_SUCCESS; 1.63 +} 1.64 + 1.65 +/* 1.66 + * build a cert nickname based on the token name and the label of the 1.67 + * certificate If the label in NULL, build a label based on the ID. 1.68 + */ 1.69 +static int toHex(int x) { return (x < 10) ? (x+'0') : (x+'a'-10); } 1.70 +#define MAX_CERT_ID 4 1.71 +#define DEFAULT_STRING "Cert ID " 1.72 +static char * 1.73 +pk11_buildNickname(PK11SlotInfo *slot,CK_ATTRIBUTE *cert_label, 1.74 + CK_ATTRIBUTE *key_label, CK_ATTRIBUTE *cert_id) 1.75 +{ 1.76 + int prefixLen = PORT_Strlen(slot->token_name); 1.77 + int suffixLen = 0; 1.78 + char *suffix = NULL; 1.79 + char buildNew[sizeof(DEFAULT_STRING)+MAX_CERT_ID*2]; 1.80 + char *next,*nickname; 1.81 + 1.82 + if (cert_label && (cert_label->ulValueLen)) { 1.83 + suffixLen = cert_label->ulValueLen; 1.84 + suffix = (char*)cert_label->pValue; 1.85 + } else if (key_label && (key_label->ulValueLen)) { 1.86 + suffixLen = key_label->ulValueLen; 1.87 + suffix = (char*)key_label->pValue; 1.88 + } else if (cert_id && cert_id->ulValueLen > 0) { 1.89 + int i,first = cert_id->ulValueLen - MAX_CERT_ID; 1.90 + int offset = sizeof(DEFAULT_STRING); 1.91 + char *idValue = (char *)cert_id->pValue; 1.92 + 1.93 + PORT_Memcpy(buildNew,DEFAULT_STRING,sizeof(DEFAULT_STRING)-1); 1.94 + next = buildNew + offset; 1.95 + if (first < 0) first = 0; 1.96 + for (i=first; i < (int) cert_id->ulValueLen; i++) { 1.97 + *next++ = toHex((idValue[i] >> 4) & 0xf); 1.98 + *next++ = toHex(idValue[i] & 0xf); 1.99 + } 1.100 + *next++ = 0; 1.101 + suffix = buildNew; 1.102 + suffixLen = PORT_Strlen(buildNew); 1.103 + } else { 1.104 + PORT_SetError( SEC_ERROR_LIBRARY_FAILURE ); 1.105 + return NULL; 1.106 + } 1.107 + 1.108 + /* if is internal key slot, add code to skip the prefix!! */ 1.109 + next = nickname = (char *)PORT_Alloc(prefixLen+1+suffixLen+1); 1.110 + if (nickname == NULL) return NULL; 1.111 + 1.112 + PORT_Memcpy(next,slot->token_name,prefixLen); 1.113 + next += prefixLen; 1.114 + *next++ = ':'; 1.115 + PORT_Memcpy(next,suffix,suffixLen); 1.116 + next += suffixLen; 1.117 + *next++ = 0; 1.118 + return nickname; 1.119 +} 1.120 + 1.121 +PRBool 1.122 +PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert, 1.123 + CK_OBJECT_HANDLE certID) 1.124 +{ 1.125 + CK_OBJECT_CLASS theClass; 1.126 + 1.127 + if (slot == NULL) return PR_FALSE; 1.128 + if (cert == NULL) return PR_FALSE; 1.129 + 1.130 + theClass = CKO_PRIVATE_KEY; 1.131 + if (pk11_LoginStillRequired(slot,NULL)) { 1.132 + theClass = CKO_PUBLIC_KEY; 1.133 + } 1.134 + if (PK11_MatchItem(slot, certID , theClass) != CK_INVALID_HANDLE) { 1.135 + return PR_TRUE; 1.136 + } 1.137 + 1.138 + if (theClass == CKO_PUBLIC_KEY) { 1.139 + SECKEYPublicKey *pubKey= CERT_ExtractPublicKey(cert); 1.140 + CK_ATTRIBUTE theTemplate; 1.141 + 1.142 + if (pubKey == NULL) { 1.143 + return PR_FALSE; 1.144 + } 1.145 + 1.146 + PK11_SETATTRS(&theTemplate,0,NULL,0); 1.147 + switch (pubKey->keyType) { 1.148 + case rsaKey: 1.149 + PK11_SETATTRS(&theTemplate,CKA_MODULUS, pubKey->u.rsa.modulus.data, 1.150 + pubKey->u.rsa.modulus.len); 1.151 + break; 1.152 + case dsaKey: 1.153 + PK11_SETATTRS(&theTemplate,CKA_VALUE, pubKey->u.dsa.publicValue.data, 1.154 + pubKey->u.dsa.publicValue.len); 1.155 + break; 1.156 + case dhKey: 1.157 + PK11_SETATTRS(&theTemplate,CKA_VALUE, pubKey->u.dh.publicValue.data, 1.158 + pubKey->u.dh.publicValue.len); 1.159 + break; 1.160 + case ecKey: 1.161 + PK11_SETATTRS(&theTemplate,CKA_EC_POINT, 1.162 + pubKey->u.ec.publicValue.data, 1.163 + pubKey->u.ec.publicValue.len); 1.164 + break; 1.165 + case keaKey: 1.166 + case fortezzaKey: 1.167 + case nullKey: 1.168 + /* fall through and return false */ 1.169 + break; 1.170 + } 1.171 + 1.172 + if (theTemplate.ulValueLen == 0) { 1.173 + SECKEY_DestroyPublicKey(pubKey); 1.174 + return PR_FALSE; 1.175 + } 1.176 + pk11_SignedToUnsigned(&theTemplate); 1.177 + if (pk11_FindObjectByTemplate(slot,&theTemplate,1) != CK_INVALID_HANDLE) { 1.178 + SECKEY_DestroyPublicKey(pubKey); 1.179 + return PR_TRUE; 1.180 + } 1.181 + SECKEY_DestroyPublicKey(pubKey); 1.182 + } 1.183 + return PR_FALSE; 1.184 +} 1.185 + 1.186 +/* 1.187 + * Check out if a cert has ID of zero. This is a magic ID that tells 1.188 + * NSS that this cert may be an automagically trusted cert. 1.189 + * The Cert has to be self signed as well. That check is done elsewhere. 1.190 + * 1.191 + */ 1.192 +PRBool 1.193 +pk11_isID0(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID) 1.194 +{ 1.195 + CK_ATTRIBUTE keyID = {CKA_ID, NULL, 0}; 1.196 + PRBool isZero = PR_FALSE; 1.197 + int i; 1.198 + CK_RV crv; 1.199 + 1.200 + 1.201 + crv = PK11_GetAttributes(NULL,slot,certID,&keyID,1); 1.202 + if (crv != CKR_OK) { 1.203 + return isZero; 1.204 + } 1.205 + 1.206 + if (keyID.ulValueLen != 0) { 1.207 + char *value = (char *)keyID.pValue; 1.208 + isZero = PR_TRUE; /* ID exists, may be zero */ 1.209 + for (i=0; i < (int) keyID.ulValueLen; i++) { 1.210 + if (value[i] != 0) { 1.211 + isZero = PR_FALSE; /* nope */ 1.212 + break; 1.213 + } 1.214 + } 1.215 + } 1.216 + PORT_Free(keyID.pValue); 1.217 + return isZero; 1.218 + 1.219 +} 1.220 + 1.221 +/* 1.222 + * Create an NSSCertificate from a slot/certID pair, return it as a 1.223 + * CERTCertificate. Optionally, output the nickname string. 1.224 + */ 1.225 +static CERTCertificate * 1.226 +pk11_fastCert(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, 1.227 + CK_ATTRIBUTE *privateLabel, char **nickptr) 1.228 +{ 1.229 + NSSCertificate *c; 1.230 + nssCryptokiObject *co = NULL; 1.231 + nssPKIObject *pkio; 1.232 + NSSToken *token; 1.233 + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); 1.234 + PRStatus status; 1.235 + 1.236 + /* Get the cryptoki object from the handle */ 1.237 + token = PK11Slot_GetNSSToken(slot); 1.238 + if (token->defaultSession) { 1.239 + co = nssCryptokiObject_Create(token, token->defaultSession, certID); 1.240 + } else { 1.241 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.242 + } 1.243 + if (!co) { 1.244 + return NULL; 1.245 + } 1.246 + 1.247 + /* Create a PKI object from the cryptoki instance */ 1.248 + pkio = nssPKIObject_Create(NULL, co, td, NULL, nssPKIMonitor); 1.249 + if (!pkio) { 1.250 + nssCryptokiObject_Destroy(co); 1.251 + return NULL; 1.252 + } 1.253 + 1.254 + /* Create a certificate */ 1.255 + c = nssCertificate_Create(pkio); 1.256 + if (!c) { 1.257 + nssPKIObject_Destroy(pkio); 1.258 + return NULL; 1.259 + } 1.260 + 1.261 + /* Build and output a nickname, if desired. 1.262 + * This must be done before calling nssTrustDomain_AddCertsToCache 1.263 + * because that function may destroy c, pkio and co! 1.264 + */ 1.265 + if ((nickptr) && (co->label)) { 1.266 + CK_ATTRIBUTE label, id; 1.267 + 1.268 + label.type = CKA_LABEL; 1.269 + label.pValue = co->label; 1.270 + label.ulValueLen = PORT_Strlen(co->label); 1.271 + 1.272 + id.type = CKA_ID; 1.273 + id.pValue = c->id.data; 1.274 + id.ulValueLen = c->id.size; 1.275 + 1.276 + *nickptr = pk11_buildNickname(slot, &label, privateLabel, &id); 1.277 + } 1.278 + 1.279 + /* This function may destroy the cert in "c" and all its subordinate 1.280 + * structures, and replace the value in "c" with the address of a 1.281 + * different NSSCertificate that it found in the cache. 1.282 + * Presumably, the nickname which we just output above remains valid. :) 1.283 + */ 1.284 + status = nssTrustDomain_AddCertsToCache(td, &c, 1); 1.285 + return STAN_GetCERTCertificateOrRelease(c); 1.286 +} 1.287 + 1.288 +/* 1.289 + * Build an CERTCertificate structure from a PKCS#11 object ID.... certID 1.290 + * Must be a CertObject. This code does not explicitly checks that. 1.291 + */ 1.292 +CERTCertificate * 1.293 +PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID, 1.294 + CK_ATTRIBUTE *privateLabel) 1.295 +{ 1.296 + char * nickname = NULL; 1.297 + CERTCertificate *cert = NULL; 1.298 + CERTCertTrust *trust; 1.299 + PRBool isFortezzaRootCA = PR_FALSE; 1.300 + PRBool swapNickname = PR_FALSE; 1.301 + 1.302 + cert = pk11_fastCert(slot,certID,privateLabel, &nickname); 1.303 + if (cert == NULL) 1.304 + goto loser; 1.305 + 1.306 + if (nickname) { 1.307 + if (cert->nickname != NULL) { 1.308 + cert->dbnickname = cert->nickname; 1.309 + } 1.310 + cert->nickname = PORT_ArenaStrdup(cert->arena,nickname); 1.311 + PORT_Free(nickname); 1.312 + nickname = NULL; 1.313 + swapNickname = PR_TRUE; 1.314 + } 1.315 + 1.316 + /* remember where this cert came from.... If we have just looked 1.317 + * it up from the database and it already has a slot, don't add a new 1.318 + * one. */ 1.319 + if (cert->slot == NULL) { 1.320 + cert->slot = PK11_ReferenceSlot(slot); 1.321 + cert->pkcs11ID = certID; 1.322 + cert->ownSlot = PR_TRUE; 1.323 + cert->series = slot->series; 1.324 + } 1.325 + 1.326 + trust = (CERTCertTrust*)PORT_ArenaAlloc(cert->arena, sizeof(CERTCertTrust)); 1.327 + if (trust == NULL) 1.328 + goto loser; 1.329 + PORT_Memset(trust,0, sizeof(CERTCertTrust)); 1.330 + 1.331 + if(! pk11_HandleTrustObject(slot, cert, trust) ) { 1.332 + unsigned int type; 1.333 + 1.334 + /* build some cert trust flags */ 1.335 + if (CERT_IsCACert(cert, &type)) { 1.336 + unsigned int trustflags = CERTDB_VALID_CA; 1.337 + 1.338 + /* Allow PKCS #11 modules to give us trusted CA's. We only accept 1.339 + * valid CA's which are self-signed here. They must have an object 1.340 + * ID of '0'. */ 1.341 + if (pk11_isID0(slot,certID) && 1.342 + cert->isRoot) { 1.343 + trustflags |= CERTDB_TRUSTED_CA; 1.344 + /* is the slot a fortezza card? allow the user or 1.345 + * admin to turn on objectSigning, but don't turn 1.346 + * full trust on explicitly */ 1.347 + if (PK11_DoesMechanism(slot,CKM_KEA_KEY_DERIVE)) { 1.348 + trust->objectSigningFlags |= CERTDB_VALID_CA; 1.349 + isFortezzaRootCA = PR_TRUE; 1.350 + } 1.351 + } 1.352 + if ((type & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) { 1.353 + trust->sslFlags |= trustflags; 1.354 + } 1.355 + if ((type & NS_CERT_TYPE_EMAIL_CA) == NS_CERT_TYPE_EMAIL_CA) { 1.356 + trust->emailFlags |= trustflags; 1.357 + } 1.358 + if ((type & NS_CERT_TYPE_OBJECT_SIGNING_CA) 1.359 + == NS_CERT_TYPE_OBJECT_SIGNING_CA) { 1.360 + trust->objectSigningFlags |= trustflags; 1.361 + } 1.362 + } 1.363 + } 1.364 + 1.365 + if (PK11_IsUserCert(slot,cert,certID)) { 1.366 + trust->sslFlags |= CERTDB_USER; 1.367 + trust->emailFlags |= CERTDB_USER; 1.368 + /* trust->objectSigningFlags |= CERTDB_USER; */ 1.369 + } 1.370 + CERT_LockCertTrust(cert); 1.371 + cert->trust = trust; 1.372 + CERT_UnlockCertTrust(cert); 1.373 + 1.374 + return cert; 1.375 + 1.376 +loser: 1.377 + if (nickname) 1.378 + PORT_Free(nickname); 1.379 + if (cert) 1.380 + CERT_DestroyCertificate(cert); 1.381 + return NULL; 1.382 +} 1.383 + 1.384 + 1.385 +/* 1.386 + * Build get a certificate from a private key 1.387 + */ 1.388 +CERTCertificate * 1.389 +PK11_GetCertFromPrivateKey(SECKEYPrivateKey *privKey) 1.390 +{ 1.391 + PK11SlotInfo *slot = privKey->pkcs11Slot; 1.392 + CK_OBJECT_HANDLE handle = privKey->pkcs11ID; 1.393 + CK_OBJECT_HANDLE certID = 1.394 + PK11_MatchItem(slot,handle,CKO_CERTIFICATE); 1.395 + CERTCertificate *cert; 1.396 + 1.397 + if (certID == CK_INVALID_HANDLE) { 1.398 + PORT_SetError(SSL_ERROR_NO_CERTIFICATE); 1.399 + return NULL; 1.400 + } 1.401 + cert = PK11_MakeCertFromHandle(slot,certID,NULL); 1.402 + return (cert); 1.403 + 1.404 +} 1.405 + 1.406 +/* 1.407 + * delete a cert and it's private key (if no other certs are pointing to the 1.408 + * private key. 1.409 + */ 1.410 +SECStatus 1.411 +PK11_DeleteTokenCertAndKey(CERTCertificate *cert,void *wincx) 1.412 +{ 1.413 + SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert,wincx); 1.414 + CK_OBJECT_HANDLE pubKey; 1.415 + PK11SlotInfo *slot = NULL; 1.416 + 1.417 + pubKey = pk11_FindPubKeyByAnyCert(cert, &slot, wincx); 1.418 + if (privKey) { 1.419 + /* For 3.4, utilize the generic cert delete function */ 1.420 + SEC_DeletePermCertificate(cert); 1.421 + PK11_DeleteTokenPrivateKey(privKey, PR_FALSE); 1.422 + } 1.423 + if ((pubKey != CK_INVALID_HANDLE) && (slot != NULL)) { 1.424 + PK11_DestroyTokenObject(slot,pubKey); 1.425 + PK11_FreeSlot(slot); 1.426 + } 1.427 + return SECSuccess; 1.428 +} 1.429 + 1.430 +/* 1.431 + * cert callback structure 1.432 + */ 1.433 +typedef struct pk11DoCertCallbackStr { 1.434 + SECStatus(* callback)(PK11SlotInfo *slot, CERTCertificate*, void *); 1.435 + SECStatus(* noslotcallback)(CERTCertificate*, void *); 1.436 + SECStatus(* itemcallback)(CERTCertificate*, SECItem *, void *); 1.437 + void *callbackArg; 1.438 +} pk11DoCertCallback; 1.439 + 1.440 + 1.441 +typedef struct pk11CertCallbackStr { 1.442 + SECStatus(* callback)(CERTCertificate*,SECItem *,void *); 1.443 + void *callbackArg; 1.444 +} pk11CertCallback; 1.445 + 1.446 +struct fake_der_cb_argstr 1.447 +{ 1.448 + SECStatus(* callback)(CERTCertificate*, SECItem *, void *); 1.449 + void *arg; 1.450 +}; 1.451 + 1.452 +static SECStatus fake_der_cb(CERTCertificate *c, void *a) 1.453 +{ 1.454 + struct fake_der_cb_argstr *fda = (struct fake_der_cb_argstr *)a; 1.455 + return (*fda->callback)(c, &c->derCert, fda->arg); 1.456 +} 1.457 + 1.458 +/* 1.459 + * Extract all the certs on a card from a slot. 1.460 + */ 1.461 +SECStatus 1.462 +PK11_TraverseSlotCerts(SECStatus(* callback)(CERTCertificate*,SECItem *,void *), 1.463 + void *arg, void *wincx) 1.464 +{ 1.465 + NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); 1.466 + struct fake_der_cb_argstr fda; 1.467 + struct nss3_cert_cbstr pk11cb; 1.468 + 1.469 + /* authenticate to the tokens first */ 1.470 + (void) pk11_TraverseAllSlots( NULL, NULL, PR_TRUE, wincx); 1.471 + 1.472 + fda.callback = callback; 1.473 + fda.arg = arg; 1.474 + pk11cb.callback = fake_der_cb; 1.475 + pk11cb.arg = &fda; 1.476 + NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb); 1.477 + return SECSuccess; 1.478 +} 1.479 + 1.480 +static void 1.481 +transfer_token_certs_to_collection(nssList *certList, NSSToken *token, 1.482 + nssPKIObjectCollection *collection) 1.483 +{ 1.484 + NSSCertificate **certs; 1.485 + PRUint32 i, count; 1.486 + NSSToken **tokens, **tp; 1.487 + count = nssList_Count(certList); 1.488 + if (count == 0) { 1.489 + return; 1.490 + } 1.491 + certs = nss_ZNEWARRAY(NULL, NSSCertificate *, count); 1.492 + if (!certs) { 1.493 + return; 1.494 + } 1.495 + nssList_GetArray(certList, (void **)certs, count); 1.496 + for (i=0; i<count; i++) { 1.497 + tokens = nssPKIObject_GetTokens(&certs[i]->object, NULL); 1.498 + if (tokens) { 1.499 + for (tp = tokens; *tp; tp++) { 1.500 + if (*tp == token) { 1.501 + nssPKIObjectCollection_AddObject(collection, 1.502 + (nssPKIObject *)certs[i]); 1.503 + } 1.504 + } 1.505 + nssTokenArray_Destroy(tokens); 1.506 + } 1.507 + CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(certs[i])); 1.508 + } 1.509 + nss_ZFreeIf(certs); 1.510 +} 1.511 + 1.512 +CERTCertificate * 1.513 +PK11_FindCertFromNickname(const char *nickname, void *wincx) 1.514 +{ 1.515 + PRStatus status; 1.516 + CERTCertificate *rvCert = NULL; 1.517 + NSSCertificate *cert = NULL; 1.518 + NSSCertificate **certs = NULL; 1.519 + static const NSSUsage usage = {PR_TRUE /* ... */ }; 1.520 + NSSToken *token; 1.521 + NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); 1.522 + PK11SlotInfo *slot = NULL; 1.523 + SECStatus rv; 1.524 + char *nickCopy; 1.525 + char *delimit = NULL; 1.526 + char *tokenName; 1.527 + 1.528 + nickCopy = PORT_Strdup(nickname); 1.529 + if (!nickCopy) { 1.530 + /* error code is set */ 1.531 + return NULL; 1.532 + } 1.533 + if ((delimit = PORT_Strchr(nickCopy,':')) != NULL) { 1.534 + tokenName = nickCopy; 1.535 + nickname = delimit + 1; 1.536 + *delimit = '\0'; 1.537 + /* find token by name */ 1.538 + token = NSSTrustDomain_FindTokenByName(defaultTD, (NSSUTF8 *)tokenName); 1.539 + if (token) { 1.540 + slot = PK11_ReferenceSlot(token->pk11slot); 1.541 + } else { 1.542 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.543 + } 1.544 + *delimit = ':'; 1.545 + } else { 1.546 + slot = PK11_GetInternalKeySlot(); 1.547 + token = PK11Slot_GetNSSToken(slot); 1.548 + } 1.549 + if (token) { 1.550 + nssList *certList; 1.551 + nssCryptokiObject **instances; 1.552 + nssPKIObjectCollection *collection; 1.553 + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; 1.554 + if (!PK11_IsPresent(slot)) { 1.555 + goto loser; 1.556 + } 1.557 + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); 1.558 + if (rv != SECSuccess) { 1.559 + goto loser; 1.560 + } 1.561 + collection = nssCertificateCollection_Create(defaultTD, NULL); 1.562 + if (!collection) { 1.563 + goto loser; 1.564 + } 1.565 + certList = nssList_Create(NULL, PR_FALSE); 1.566 + if (!certList) { 1.567 + nssPKIObjectCollection_Destroy(collection); 1.568 + goto loser; 1.569 + } 1.570 + (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, 1.571 + nickname, 1.572 + certList); 1.573 + transfer_token_certs_to_collection(certList, token, collection); 1.574 + instances = nssToken_FindCertificatesByNickname(token, 1.575 + NULL, 1.576 + nickname, 1.577 + tokenOnly, 1.578 + 0, 1.579 + &status); 1.580 + nssPKIObjectCollection_AddInstances(collection, instances, 0); 1.581 + nss_ZFreeIf(instances); 1.582 + /* if it wasn't found, repeat the process for email address */ 1.583 + if (nssPKIObjectCollection_Count(collection) == 0 && 1.584 + PORT_Strchr(nickname, '@') != NULL) 1.585 + { 1.586 + char* lowercaseName = CERT_FixupEmailAddr(nickname); 1.587 + if (lowercaseName) { 1.588 + (void)nssTrustDomain_GetCertsForEmailAddressFromCache(defaultTD, 1.589 + lowercaseName, 1.590 + certList); 1.591 + transfer_token_certs_to_collection(certList, token, collection); 1.592 + instances = nssToken_FindCertificatesByEmail(token, 1.593 + NULL, 1.594 + lowercaseName, 1.595 + tokenOnly, 1.596 + 0, 1.597 + &status); 1.598 + nssPKIObjectCollection_AddInstances(collection, instances, 0); 1.599 + nss_ZFreeIf(instances); 1.600 + PORT_Free(lowercaseName); 1.601 + } 1.602 + } 1.603 + certs = nssPKIObjectCollection_GetCertificates(collection, 1.604 + NULL, 0, NULL); 1.605 + nssPKIObjectCollection_Destroy(collection); 1.606 + if (certs) { 1.607 + cert = nssCertificateArray_FindBestCertificate(certs, NULL, 1.608 + &usage, NULL); 1.609 + if (cert) { 1.610 + rvCert = STAN_GetCERTCertificateOrRelease(cert); 1.611 + } 1.612 + nssCertificateArray_Destroy(certs); 1.613 + } 1.614 + nssList_Destroy(certList); 1.615 + } 1.616 + if (slot) { 1.617 + PK11_FreeSlot(slot); 1.618 + } 1.619 + if (nickCopy) PORT_Free(nickCopy); 1.620 + return rvCert; 1.621 +loser: 1.622 + if (slot) { 1.623 + PK11_FreeSlot(slot); 1.624 + } 1.625 + if (nickCopy) PORT_Free(nickCopy); 1.626 + return NULL; 1.627 +} 1.628 + 1.629 +/* Traverse slots callback */ 1.630 +typedef struct FindCertsEmailArgStr { 1.631 + char *email; 1.632 + CERTCertList *certList; 1.633 +} FindCertsEmailArg; 1.634 + 1.635 +SECStatus 1.636 +FindCertsEmailCallback(CERTCertificate *cert, SECItem *item, void *arg) 1.637 +{ 1.638 + FindCertsEmailArg *cbparam = (FindCertsEmailArg *) arg; 1.639 + const char *cert_email = CERT_GetFirstEmailAddress(cert); 1.640 + PRBool found = PR_FALSE; 1.641 + 1.642 + /* Email address present in certificate? */ 1.643 + if (cert_email == NULL){ 1.644 + return SECSuccess; 1.645 + } 1.646 + 1.647 + /* Parameter correctly set? */ 1.648 + if (cbparam->email == NULL) { 1.649 + return SECFailure; 1.650 + } 1.651 + 1.652 + /* Loop over all email addresses */ 1.653 + do { 1.654 + if (!strcmp(cert_email, cbparam->email)) { 1.655 + /* found one matching email address */ 1.656 + PRTime now = PR_Now(); 1.657 + found = PR_TRUE; 1.658 + CERT_AddCertToListSorted(cbparam->certList, 1.659 + CERT_DupCertificate(cert), 1.660 + CERT_SortCBValidity, &now); 1.661 + } 1.662 + cert_email = CERT_GetNextEmailAddress(cert, cert_email); 1.663 + } while (cert_email && !found); 1.664 + 1.665 + return SECSuccess; 1.666 +} 1.667 + 1.668 +/* Find all certificates with matching email address */ 1.669 +CERTCertList * 1.670 +PK11_FindCertsFromEmailAddress(const char *email, void *wincx) 1.671 +{ 1.672 + FindCertsEmailArg cbparam; 1.673 + SECStatus rv; 1.674 + 1.675 + cbparam.certList = CERT_NewCertList(); 1.676 + if (cbparam.certList == NULL) { 1.677 + return NULL; 1.678 + } 1.679 + 1.680 + cbparam.email = CERT_FixupEmailAddr(email); 1.681 + if (cbparam.email == NULL) { 1.682 + CERT_DestroyCertList(cbparam.certList); 1.683 + return NULL; 1.684 + } 1.685 + 1.686 + rv = PK11_TraverseSlotCerts(FindCertsEmailCallback, &cbparam, NULL); 1.687 + if (rv != SECSuccess) { 1.688 + CERT_DestroyCertList(cbparam.certList); 1.689 + PORT_Free(cbparam.email); 1.690 + return NULL; 1.691 + } 1.692 + 1.693 + /* empty list? */ 1.694 + if (CERT_LIST_HEAD(cbparam.certList) == NULL || 1.695 + CERT_LIST_END(CERT_LIST_HEAD(cbparam.certList), cbparam.certList)) { 1.696 + CERT_DestroyCertList(cbparam.certList); 1.697 + cbparam.certList = NULL; 1.698 + } 1.699 + 1.700 + PORT_Free(cbparam.email); 1.701 + return cbparam.certList; 1.702 +} 1.703 + 1.704 + 1.705 +CERTCertList * 1.706 +PK11_FindCertsFromNickname(const char *nickname, void *wincx) 1.707 +{ 1.708 + char *nickCopy; 1.709 + char *delimit = NULL; 1.710 + char *tokenName; 1.711 + int i; 1.712 + CERTCertList *certList = NULL; 1.713 + nssPKIObjectCollection *collection = NULL; 1.714 + NSSCertificate **foundCerts = NULL; 1.715 + NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); 1.716 + NSSCertificate *c; 1.717 + NSSToken *token; 1.718 + PK11SlotInfo *slot; 1.719 + SECStatus rv; 1.720 + 1.721 + nickCopy = PORT_Strdup(nickname); 1.722 + if (!nickCopy) { 1.723 + /* error code is set */ 1.724 + return NULL; 1.725 + } 1.726 + if ((delimit = PORT_Strchr(nickCopy,':')) != NULL) { 1.727 + tokenName = nickCopy; 1.728 + nickname = delimit + 1; 1.729 + *delimit = '\0'; 1.730 + /* find token by name */ 1.731 + token = NSSTrustDomain_FindTokenByName(defaultTD, (NSSUTF8 *)tokenName); 1.732 + if (token) { 1.733 + slot = PK11_ReferenceSlot(token->pk11slot); 1.734 + } else { 1.735 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.736 + slot = NULL; 1.737 + } 1.738 + *delimit = ':'; 1.739 + } else { 1.740 + slot = PK11_GetInternalKeySlot(); 1.741 + token = PK11Slot_GetNSSToken(slot); 1.742 + } 1.743 + if (token) { 1.744 + PRStatus status; 1.745 + nssList *nameList; 1.746 + nssCryptokiObject **instances; 1.747 + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; 1.748 + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); 1.749 + if (rv != SECSuccess) { 1.750 + PK11_FreeSlot(slot); 1.751 + if (nickCopy) PORT_Free(nickCopy); 1.752 + return NULL; 1.753 + } 1.754 + collection = nssCertificateCollection_Create(defaultTD, NULL); 1.755 + if (!collection) { 1.756 + PK11_FreeSlot(slot); 1.757 + if (nickCopy) PORT_Free(nickCopy); 1.758 + return NULL; 1.759 + } 1.760 + nameList = nssList_Create(NULL, PR_FALSE); 1.761 + if (!nameList) { 1.762 + PK11_FreeSlot(slot); 1.763 + if (nickCopy) PORT_Free(nickCopy); 1.764 + return NULL; 1.765 + } 1.766 + (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, 1.767 + nickname, 1.768 + nameList); 1.769 + transfer_token_certs_to_collection(nameList, token, collection); 1.770 + instances = nssToken_FindCertificatesByNickname(token, 1.771 + NULL, 1.772 + nickname, 1.773 + tokenOnly, 1.774 + 0, 1.775 + &status); 1.776 + nssPKIObjectCollection_AddInstances(collection, instances, 0); 1.777 + nss_ZFreeIf(instances); 1.778 + 1.779 + /* if it wasn't found, repeat the process for email address */ 1.780 + if (nssPKIObjectCollection_Count(collection) == 0 && 1.781 + PORT_Strchr(nickname, '@') != NULL) 1.782 + { 1.783 + char* lowercaseName = CERT_FixupEmailAddr(nickname); 1.784 + if (lowercaseName) { 1.785 + (void)nssTrustDomain_GetCertsForEmailAddressFromCache(defaultTD, 1.786 + lowercaseName, 1.787 + nameList); 1.788 + transfer_token_certs_to_collection(nameList, token, collection); 1.789 + instances = nssToken_FindCertificatesByEmail(token, 1.790 + NULL, 1.791 + lowercaseName, 1.792 + tokenOnly, 1.793 + 0, 1.794 + &status); 1.795 + nssPKIObjectCollection_AddInstances(collection, instances, 0); 1.796 + nss_ZFreeIf(instances); 1.797 + PORT_Free(lowercaseName); 1.798 + } 1.799 + } 1.800 + 1.801 + nssList_Destroy(nameList); 1.802 + foundCerts = nssPKIObjectCollection_GetCertificates(collection, 1.803 + NULL, 0, NULL); 1.804 + nssPKIObjectCollection_Destroy(collection); 1.805 + } 1.806 + if (slot) { 1.807 + PK11_FreeSlot(slot); 1.808 + } 1.809 + if (nickCopy) PORT_Free(nickCopy); 1.810 + if (foundCerts) { 1.811 + PRTime now = PR_Now(); 1.812 + certList = CERT_NewCertList(); 1.813 + for (i=0, c = *foundCerts; c; c = foundCerts[++i]) { 1.814 + if (certList) { 1.815 + CERTCertificate *certCert = STAN_GetCERTCertificateOrRelease(c); 1.816 + /* c may be invalid after this, don't reference it */ 1.817 + if (certCert) { 1.818 + /* CERT_AddCertToListSorted adopts certCert */ 1.819 + CERT_AddCertToListSorted(certList, certCert, 1.820 + CERT_SortCBValidity, &now); 1.821 + } 1.822 + } else { 1.823 + nssCertificate_Destroy(c); 1.824 + } 1.825 + } 1.826 + if (certList && CERT_LIST_HEAD(certList) == NULL) { 1.827 + CERT_DestroyCertList(certList); 1.828 + certList = NULL; 1.829 + } 1.830 + /* all the certs have been adopted or freed, free the raw array */ 1.831 + nss_ZFreeIf(foundCerts); 1.832 + } 1.833 + return certList; 1.834 +} 1.835 + 1.836 +/* 1.837 + * extract a key ID for a certificate... 1.838 + * NOTE: We call this function from PKCS11.c If we ever use 1.839 + * pkcs11 to extract the public key (we currently do not), this will break. 1.840 + */ 1.841 +SECItem * 1.842 +PK11_GetPubIndexKeyID(CERTCertificate *cert) 1.843 +{ 1.844 + SECKEYPublicKey *pubk; 1.845 + SECItem *newItem = NULL; 1.846 + 1.847 + pubk = CERT_ExtractPublicKey(cert); 1.848 + if (pubk == NULL) return NULL; 1.849 + 1.850 + switch (pubk->keyType) { 1.851 + case rsaKey: 1.852 + newItem = SECITEM_DupItem(&pubk->u.rsa.modulus); 1.853 + break; 1.854 + case dsaKey: 1.855 + newItem = SECITEM_DupItem(&pubk->u.dsa.publicValue); 1.856 + break; 1.857 + case dhKey: 1.858 + newItem = SECITEM_DupItem(&pubk->u.dh.publicValue); 1.859 + break; 1.860 + case ecKey: 1.861 + newItem = SECITEM_DupItem(&pubk->u.ec.publicValue); 1.862 + break; 1.863 + case fortezzaKey: 1.864 + default: 1.865 + newItem = NULL; /* Fortezza Fix later... */ 1.866 + } 1.867 + SECKEY_DestroyPublicKey(pubk); 1.868 + /* make hash of it */ 1.869 + return newItem; 1.870 +} 1.871 + 1.872 +/* 1.873 + * generate a CKA_ID from a certificate. 1.874 + */ 1.875 +SECItem * 1.876 +pk11_mkcertKeyID(CERTCertificate *cert) 1.877 +{ 1.878 + SECItem *pubKeyData = PK11_GetPubIndexKeyID(cert) ; 1.879 + SECItem *certCKA_ID; 1.880 + 1.881 + if (pubKeyData == NULL) return NULL; 1.882 + 1.883 + certCKA_ID = PK11_MakeIDFromPubKey(pubKeyData); 1.884 + SECITEM_FreeItem(pubKeyData,PR_TRUE); 1.885 + return certCKA_ID; 1.886 +} 1.887 + 1.888 +/* 1.889 + * Write the cert into the token. 1.890 + */ 1.891 +SECStatus 1.892 +PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, 1.893 + CK_OBJECT_HANDLE key, const char *nickname, 1.894 + PRBool includeTrust) 1.895 +{ 1.896 + PRStatus status; 1.897 + NSSCertificate *c; 1.898 + nssCryptokiObject *keyobj, *certobj; 1.899 + NSSToken *token = PK11Slot_GetNSSToken(slot); 1.900 + SECItem *keyID = pk11_mkcertKeyID(cert); 1.901 + char *emailAddr = NULL; 1.902 + nssCertificateStoreTrace lockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; 1.903 + nssCertificateStoreTrace unlockTrace = {NULL, NULL, PR_FALSE, PR_FALSE}; 1.904 + 1.905 + if (keyID == NULL) { 1.906 + goto loser; /* error code should be set already */ 1.907 + } 1.908 + if (!token) { 1.909 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.910 + goto loser; 1.911 + } 1.912 + 1.913 + if (PK11_IsInternal(slot) && cert->emailAddr && cert->emailAddr[0]) { 1.914 + emailAddr = cert->emailAddr; 1.915 + } 1.916 + 1.917 + /* need to get the cert as a stan cert */ 1.918 + if (cert->nssCertificate) { 1.919 + c = cert->nssCertificate; 1.920 + } else { 1.921 + c = STAN_GetNSSCertificate(cert); 1.922 + if (c == NULL) { 1.923 + goto loser; 1.924 + } 1.925 + } 1.926 + 1.927 + /* set the id for the cert */ 1.928 + nssItem_Create(c->object.arena, &c->id, keyID->len, keyID->data); 1.929 + if (!c->id.data) { 1.930 + goto loser; 1.931 + } 1.932 + 1.933 + if (key != CK_INVALID_HANDLE) { 1.934 + /* create an object for the key, ... */ 1.935 + keyobj = nss_ZNEW(NULL, nssCryptokiObject); 1.936 + if (!keyobj) { 1.937 + goto loser; 1.938 + } 1.939 + keyobj->token = nssToken_AddRef(token); 1.940 + keyobj->handle = key; 1.941 + keyobj->isTokenObject = PR_TRUE; 1.942 + 1.943 + /* ... in order to set matching attributes for the key */ 1.944 + status = nssCryptokiPrivateKey_SetCertificate(keyobj, NULL, nickname, 1.945 + &c->id, &c->subject); 1.946 + nssCryptokiObject_Destroy(keyobj); 1.947 + if (status != PR_SUCCESS) { 1.948 + goto loser; 1.949 + } 1.950 + } 1.951 + 1.952 + /* do the token import */ 1.953 + certobj = nssToken_ImportCertificate(token, NULL, 1.954 + NSSCertificateType_PKIX, 1.955 + &c->id, 1.956 + nickname, 1.957 + &c->encoding, 1.958 + &c->issuer, 1.959 + &c->subject, 1.960 + &c->serial, 1.961 + emailAddr, 1.962 + PR_TRUE); 1.963 + if (!certobj) { 1.964 + if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE) { 1.965 + PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); 1.966 + SECITEM_FreeItem(keyID,PR_TRUE); 1.967 + return SECFailure; 1.968 + } 1.969 + goto loser; 1.970 + } 1.971 + 1.972 + if (c->object.cryptoContext) { 1.973 + /* Delete the temp instance */ 1.974 + NSSCryptoContext *cc = c->object.cryptoContext; 1.975 + nssCertificateStore_Lock(cc->certStore, &lockTrace); 1.976 + nssCertificateStore_RemoveCertLOCKED(cc->certStore, c); 1.977 + nssCertificateStore_Unlock(cc->certStore, &lockTrace, &unlockTrace); 1.978 + c->object.cryptoContext = NULL; 1.979 + cert->istemp = PR_FALSE; 1.980 + cert->isperm = PR_TRUE; 1.981 + } 1.982 + 1.983 + /* add the new instance to the cert, force an update of the 1.984 + * CERTCertificate, and finish 1.985 + */ 1.986 + nssPKIObject_AddInstance(&c->object, certobj); 1.987 + /* nssTrustDomain_AddCertsToCache may release a reference to 'c' and 1.988 + * replace 'c' by a different value. So we add a reference to 'c' to 1.989 + * prevent 'c' from being destroyed. */ 1.990 + nssCertificate_AddRef(c); 1.991 + nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1); 1.992 + /* XXX should we pass the original value of 'c' to 1.993 + * STAN_ForceCERTCertificateUpdate? */ 1.994 + (void)STAN_ForceCERTCertificateUpdate(c); 1.995 + nssCertificate_Destroy(c); 1.996 + SECITEM_FreeItem(keyID,PR_TRUE); 1.997 + return SECSuccess; 1.998 +loser: 1.999 + CERT_MapStanError(); 1.1000 + SECITEM_FreeItem(keyID,PR_TRUE); 1.1001 + if (PORT_GetError() != SEC_ERROR_TOKEN_NOT_LOGGED_IN) { 1.1002 + PORT_SetError(SEC_ERROR_ADDING_CERT); 1.1003 + } 1.1004 + return SECFailure; 1.1005 +} 1.1006 + 1.1007 +SECStatus 1.1008 +PK11_ImportDERCert(PK11SlotInfo *slot, SECItem *derCert, 1.1009 + CK_OBJECT_HANDLE key, char *nickname, PRBool includeTrust) 1.1010 +{ 1.1011 + CERTCertificate *cert; 1.1012 + SECStatus rv; 1.1013 + 1.1014 + cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 1.1015 + derCert, NULL, PR_FALSE, PR_TRUE); 1.1016 + if (cert == NULL) return SECFailure; 1.1017 + 1.1018 + rv = PK11_ImportCert(slot, cert, key, nickname, includeTrust); 1.1019 + CERT_DestroyCertificate (cert); 1.1020 + return rv; 1.1021 +} 1.1022 + 1.1023 +/* 1.1024 + * get a certificate handle, look at the cached handle first.. 1.1025 + */ 1.1026 +CK_OBJECT_HANDLE 1.1027 +pk11_getcerthandle(PK11SlotInfo *slot, CERTCertificate *cert, 1.1028 + CK_ATTRIBUTE *theTemplate,int tsize) 1.1029 +{ 1.1030 + CK_OBJECT_HANDLE certh; 1.1031 + 1.1032 + if (cert->slot == slot) { 1.1033 + certh = cert->pkcs11ID; 1.1034 + if ((certh == CK_INVALID_HANDLE) || 1.1035 + (cert->series != slot->series)) { 1.1036 + certh = pk11_FindObjectByTemplate(slot,theTemplate,tsize); 1.1037 + cert->pkcs11ID = certh; 1.1038 + cert->series = slot->series; 1.1039 + } 1.1040 + } else { 1.1041 + certh = pk11_FindObjectByTemplate(slot,theTemplate,tsize); 1.1042 + } 1.1043 + return certh; 1.1044 +} 1.1045 + 1.1046 +/* 1.1047 + * return the private key From a given Cert 1.1048 + */ 1.1049 +SECKEYPrivateKey * 1.1050 +PK11_FindPrivateKeyFromCert(PK11SlotInfo *slot, CERTCertificate *cert, 1.1051 + void *wincx) 1.1052 +{ 1.1053 + int err; 1.1054 + CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; 1.1055 + CK_ATTRIBUTE theTemplate[] = { 1.1056 + { CKA_VALUE, NULL, 0 }, 1.1057 + { CKA_CLASS, NULL, 0 } 1.1058 + }; 1.1059 + /* if you change the array, change the variable below as well */ 1.1060 + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); 1.1061 + CK_OBJECT_HANDLE certh; 1.1062 + CK_OBJECT_HANDLE keyh; 1.1063 + CK_ATTRIBUTE *attrs = theTemplate; 1.1064 + PRBool needLogin; 1.1065 + SECStatus rv; 1.1066 + 1.1067 + PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, 1.1068 + cert->derCert.len); attrs++; 1.1069 + PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); 1.1070 + 1.1071 + /* 1.1072 + * issue the find 1.1073 + */ 1.1074 + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); 1.1075 + if (rv != SECSuccess) { 1.1076 + return NULL; 1.1077 + } 1.1078 + 1.1079 + certh = pk11_getcerthandle(slot,cert,theTemplate,tsize); 1.1080 + if (certh == CK_INVALID_HANDLE) { 1.1081 + return NULL; 1.1082 + } 1.1083 + /* 1.1084 + * prevent a login race condition. If slot is logged in between 1.1085 + * our call to pk11_LoginStillRequired and the 1.1086 + * PK11_MatchItem. The matchItem call will either succeed, or 1.1087 + * we will call it one more time after calling PK11_Authenticate 1.1088 + * (which is a noop on an authenticated token). 1.1089 + */ 1.1090 + needLogin = pk11_LoginStillRequired(slot,wincx); 1.1091 + keyh = PK11_MatchItem(slot,certh,CKO_PRIVATE_KEY); 1.1092 + if ((keyh == CK_INVALID_HANDLE) && needLogin && 1.1093 + (SSL_ERROR_NO_CERTIFICATE == (err = PORT_GetError()) || 1.1094 + SEC_ERROR_TOKEN_NOT_LOGGED_IN == err )) { 1.1095 + /* try it again authenticated */ 1.1096 + rv = PK11_Authenticate(slot, PR_TRUE, wincx); 1.1097 + if (rv != SECSuccess) { 1.1098 + return NULL; 1.1099 + } 1.1100 + keyh = PK11_MatchItem(slot,certh,CKO_PRIVATE_KEY); 1.1101 + } 1.1102 + if (keyh == CK_INVALID_HANDLE) { 1.1103 + return NULL; 1.1104 + } 1.1105 + return PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyh, wincx); 1.1106 +} 1.1107 + 1.1108 +/* 1.1109 + * import a cert for a private key we have already generated. Set the label 1.1110 + * on both to be the nickname. This is for the Key Gen, orphaned key case. 1.1111 + */ 1.1112 +PK11SlotInfo * 1.1113 +PK11_KeyForCertExists(CERTCertificate *cert, CK_OBJECT_HANDLE *keyPtr, 1.1114 + void *wincx) 1.1115 +{ 1.1116 + PK11SlotList *list; 1.1117 + PK11SlotListElement *le; 1.1118 + SECItem *keyID; 1.1119 + CK_OBJECT_HANDLE key; 1.1120 + PK11SlotInfo *slot = NULL; 1.1121 + SECStatus rv; 1.1122 + int err; 1.1123 + 1.1124 + keyID = pk11_mkcertKeyID(cert); 1.1125 + /* get them all! */ 1.1126 + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); 1.1127 + if ((keyID == NULL) || (list == NULL)) { 1.1128 + if (keyID) SECITEM_FreeItem(keyID,PR_TRUE); 1.1129 + if (list) PK11_FreeSlotList(list); 1.1130 + return NULL; 1.1131 + } 1.1132 + 1.1133 + /* Look for the slot that holds the Key */ 1.1134 + for (le = list->head ; le; le = le->next) { 1.1135 + /* 1.1136 + * prevent a login race condition. If le->slot is logged in between 1.1137 + * our call to pk11_LoginStillRequired and the 1.1138 + * pk11_FindPrivateKeyFromCertID, the find will either succeed, or 1.1139 + * we will call it one more time after calling PK11_Authenticate 1.1140 + * (which is a noop on an authenticated token). 1.1141 + */ 1.1142 + PRBool needLogin = pk11_LoginStillRequired(le->slot,wincx); 1.1143 + key = pk11_FindPrivateKeyFromCertID(le->slot,keyID); 1.1144 + if ((key == CK_INVALID_HANDLE) && needLogin && 1.1145 + (SSL_ERROR_NO_CERTIFICATE == (err = PORT_GetError()) || 1.1146 + SEC_ERROR_TOKEN_NOT_LOGGED_IN == err )) { 1.1147 + /* authenticate and try again */ 1.1148 + rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); 1.1149 + if (rv != SECSuccess) continue; 1.1150 + key = pk11_FindPrivateKeyFromCertID(le->slot,keyID); 1.1151 + } 1.1152 + if (key != CK_INVALID_HANDLE) { 1.1153 + slot = PK11_ReferenceSlot(le->slot); 1.1154 + if (keyPtr) *keyPtr = key; 1.1155 + break; 1.1156 + } 1.1157 + } 1.1158 + 1.1159 + SECITEM_FreeItem(keyID,PR_TRUE); 1.1160 + PK11_FreeSlotList(list); 1.1161 + return slot; 1.1162 + 1.1163 +} 1.1164 +/* 1.1165 + * import a cert for a private key we have already generated. Set the label 1.1166 + * on both to be the nickname. This is for the Key Gen, orphaned key case. 1.1167 + */ 1.1168 +PK11SlotInfo * 1.1169 +PK11_KeyForDERCertExists(SECItem *derCert, CK_OBJECT_HANDLE *keyPtr, 1.1170 + void *wincx) 1.1171 +{ 1.1172 + CERTCertificate *cert; 1.1173 + PK11SlotInfo *slot = NULL; 1.1174 + 1.1175 + /* letting this use go -- the only thing that the cert is used for is 1.1176 + * to get the ID attribute. 1.1177 + */ 1.1178 + cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); 1.1179 + if (cert == NULL) return NULL; 1.1180 + 1.1181 + slot = PK11_KeyForCertExists(cert, keyPtr, wincx); 1.1182 + CERT_DestroyCertificate (cert); 1.1183 + return slot; 1.1184 +} 1.1185 + 1.1186 +PK11SlotInfo * 1.1187 +PK11_ImportCertForKey(CERTCertificate *cert, const char *nickname, 1.1188 + void *wincx) 1.1189 +{ 1.1190 + PK11SlotInfo *slot = NULL; 1.1191 + CK_OBJECT_HANDLE key; 1.1192 + 1.1193 + slot = PK11_KeyForCertExists(cert,&key,wincx); 1.1194 + 1.1195 + if (slot) { 1.1196 + if (PK11_ImportCert(slot,cert,key,nickname,PR_FALSE) != SECSuccess) { 1.1197 + PK11_FreeSlot(slot); 1.1198 + slot = NULL; 1.1199 + } 1.1200 + } else { 1.1201 + PORT_SetError(SEC_ERROR_ADDING_CERT); 1.1202 + } 1.1203 + 1.1204 + return slot; 1.1205 +} 1.1206 + 1.1207 +PK11SlotInfo * 1.1208 +PK11_ImportDERCertForKey(SECItem *derCert, char *nickname,void *wincx) 1.1209 +{ 1.1210 + CERTCertificate *cert; 1.1211 + PK11SlotInfo *slot = NULL; 1.1212 + 1.1213 + cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 1.1214 + derCert, NULL, PR_FALSE, PR_TRUE); 1.1215 + if (cert == NULL) return NULL; 1.1216 + 1.1217 + slot = PK11_ImportCertForKey(cert, nickname, wincx); 1.1218 + CERT_DestroyCertificate (cert); 1.1219 + return slot; 1.1220 +} 1.1221 + 1.1222 +static CK_OBJECT_HANDLE 1.1223 +pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, 1.1224 + CK_ATTRIBUTE *searchTemplate, int count, void *wincx) 1.1225 +{ 1.1226 + PK11SlotList *list; 1.1227 + PK11SlotListElement *le; 1.1228 + CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE; 1.1229 + PK11SlotInfo *slot = NULL; 1.1230 + SECStatus rv; 1.1231 + 1.1232 + *slotPtr = NULL; 1.1233 + 1.1234 + /* get them all! */ 1.1235 + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); 1.1236 + if (list == NULL) { 1.1237 + return CK_INVALID_HANDLE; 1.1238 + } 1.1239 + 1.1240 + 1.1241 + /* Look for the slot that holds the Key */ 1.1242 + for (le = list->head ; le; le = le->next) { 1.1243 + rv = pk11_AuthenticateUnfriendly(le->slot, PR_TRUE, wincx); 1.1244 + if (rv != SECSuccess) continue; 1.1245 + 1.1246 + certHandle = pk11_FindObjectByTemplate(le->slot,searchTemplate,count); 1.1247 + if (certHandle != CK_INVALID_HANDLE) { 1.1248 + slot = PK11_ReferenceSlot(le->slot); 1.1249 + break; 1.1250 + } 1.1251 + } 1.1252 + 1.1253 + PK11_FreeSlotList(list); 1.1254 + 1.1255 + if (slot == NULL) { 1.1256 + return CK_INVALID_HANDLE; 1.1257 + } 1.1258 + *slotPtr = slot; 1.1259 + return certHandle; 1.1260 +} 1.1261 + 1.1262 +CERTCertificate * 1.1263 +PK11_FindCertByIssuerAndSNOnToken(PK11SlotInfo *slot, 1.1264 + CERTIssuerAndSN *issuerSN, void *wincx) 1.1265 +{ 1.1266 + CERTCertificate *rvCert = NULL; 1.1267 + NSSCertificate *cert = NULL; 1.1268 + NSSDER issuer, serial; 1.1269 + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); 1.1270 + NSSToken *token = slot->nssToken; 1.1271 + nssSession *session; 1.1272 + nssCryptokiObject *instance = NULL; 1.1273 + nssPKIObject *object = NULL; 1.1274 + SECItem *derSerial; 1.1275 + PRStatus status; 1.1276 + 1.1277 + if (!issuerSN || !issuerSN->derIssuer.data || !issuerSN->derIssuer.len || 1.1278 + !issuerSN->serialNumber.data || !issuerSN->serialNumber.len || 1.1279 + issuerSN->derIssuer.len > CERT_MAX_DN_BYTES || 1.1280 + issuerSN->serialNumber.len > CERT_MAX_SERIAL_NUMBER_BYTES ) { 1.1281 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1282 + return NULL; 1.1283 + } 1.1284 + 1.1285 + /* Paranoia */ 1.1286 + if (token == NULL) { 1.1287 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.1288 + return NULL; 1.1289 + } 1.1290 + 1.1291 + 1.1292 + /* PKCS#11 needs to use DER-encoded serial numbers. Create a 1.1293 + * CERTIssuerAndSN that actually has the encoded value and pass that 1.1294 + * to PKCS#11 (and the crypto context). 1.1295 + */ 1.1296 + derSerial = SEC_ASN1EncodeItem(NULL, NULL, 1.1297 + &issuerSN->serialNumber, 1.1298 + SEC_ASN1_GET(SEC_IntegerTemplate)); 1.1299 + if (!derSerial) { 1.1300 + return NULL; 1.1301 + } 1.1302 + 1.1303 + NSSITEM_FROM_SECITEM(&issuer, &issuerSN->derIssuer); 1.1304 + NSSITEM_FROM_SECITEM(&serial, derSerial); 1.1305 + 1.1306 + session = nssToken_GetDefaultSession(token); 1.1307 + if (!session) { 1.1308 + goto loser; 1.1309 + } 1.1310 + 1.1311 + instance = nssToken_FindCertificateByIssuerAndSerialNumber(token,session, 1.1312 + &issuer, &serial, nssTokenSearchType_TokenForced, &status); 1.1313 + 1.1314 + SECITEM_FreeItem(derSerial, PR_TRUE); 1.1315 + 1.1316 + if (!instance) { 1.1317 + goto loser; 1.1318 + } 1.1319 + object = nssPKIObject_Create(NULL, instance, td, NULL, nssPKIMonitor); 1.1320 + if (!object) { 1.1321 + goto loser; 1.1322 + } 1.1323 + instance = NULL; /* adopted by the previous call */ 1.1324 + cert = nssCertificate_Create(object); 1.1325 + if (!cert) { 1.1326 + goto loser; 1.1327 + } 1.1328 + object = NULL; /* adopted by the previous call */ 1.1329 + nssTrustDomain_AddCertsToCache(td, &cert,1); 1.1330 + /* on failure, cert is freed below */ 1.1331 + rvCert = STAN_GetCERTCertificate(cert); 1.1332 + if (!rvCert) { 1.1333 + goto loser; 1.1334 + } 1.1335 + return rvCert; 1.1336 + 1.1337 +loser: 1.1338 + if (instance) { 1.1339 + nssCryptokiObject_Destroy(instance); 1.1340 + } 1.1341 + if (object) { 1.1342 + nssPKIObject_Destroy(object); 1.1343 + } 1.1344 + if (cert) { 1.1345 + nssCertificate_Destroy(cert); 1.1346 + } 1.1347 + return NULL; 1.1348 +} 1.1349 + 1.1350 +static PRCallOnceType keyIDHashCallOnce; 1.1351 + 1.1352 +static PRStatus PR_CALLBACK 1.1353 +pk11_keyIDHash_populate(void *wincx) 1.1354 +{ 1.1355 + CERTCertList *certList; 1.1356 + CERTCertListNode *node = NULL; 1.1357 + SECItem subjKeyID = {siBuffer, NULL, 0}; 1.1358 + SECItem *slotid = NULL; 1.1359 + SECMODModuleList *modules, *mlp; 1.1360 + SECMODListLock *moduleLock; 1.1361 + int i; 1.1362 + 1.1363 + certList = PK11_ListCerts(PK11CertListUser, wincx); 1.1364 + if (!certList) { 1.1365 + return PR_FAILURE; 1.1366 + } 1.1367 + 1.1368 + for (node = CERT_LIST_HEAD(certList); 1.1369 + !CERT_LIST_END(node, certList); 1.1370 + node = CERT_LIST_NEXT(node)) { 1.1371 + if (CERT_FindSubjectKeyIDExtension(node->cert, 1.1372 + &subjKeyID) == SECSuccess && 1.1373 + subjKeyID.data != NULL) { 1.1374 + cert_AddSubjectKeyIDMapping(&subjKeyID, node->cert); 1.1375 + SECITEM_FreeItem(&subjKeyID, PR_FALSE); 1.1376 + } 1.1377 + } 1.1378 + CERT_DestroyCertList(certList); 1.1379 + 1.1380 + /* 1.1381 + * Record the state of each slot in a hash. The concatenation of slotID 1.1382 + * and moduleID is used as its key, with the slot series as its value. 1.1383 + */ 1.1384 + slotid = SECITEM_AllocItem(NULL, NULL, 1.1385 + sizeof(CK_SLOT_ID) + sizeof(SECMODModuleID)); 1.1386 + if (!slotid) { 1.1387 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1388 + return PR_FAILURE; 1.1389 + } 1.1390 + moduleLock = SECMOD_GetDefaultModuleListLock(); 1.1391 + if (!moduleLock) { 1.1392 + PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1.1393 + return PR_FAILURE; 1.1394 + } 1.1395 + SECMOD_GetReadLock(moduleLock); 1.1396 + modules = SECMOD_GetDefaultModuleList(); 1.1397 + for (mlp = modules; mlp; mlp = mlp->next) { 1.1398 + for (i = 0; i < mlp->module->slotCount; i++) { 1.1399 + memcpy(slotid->data, &mlp->module->slots[i]->slotID, 1.1400 + sizeof(CK_SLOT_ID)); 1.1401 + memcpy(&slotid->data[sizeof(CK_SLOT_ID)], &mlp->module->moduleID, 1.1402 + sizeof(SECMODModuleID)); 1.1403 + cert_UpdateSubjectKeyIDSlotCheck(slotid, 1.1404 + mlp->module->slots[i]->series); 1.1405 + } 1.1406 + } 1.1407 + SECMOD_ReleaseReadLock(moduleLock); 1.1408 + SECITEM_FreeItem(slotid, PR_TRUE); 1.1409 + 1.1410 + return PR_SUCCESS; 1.1411 +} 1.1412 + 1.1413 +/* 1.1414 + * We're looking for a cert which we have the private key for that's on the 1.1415 + * list of recipients. This searches one slot. 1.1416 + * this is the new version for NSS SMIME code 1.1417 + * this stuff should REALLY be in the SMIME code, but some things in here are not public 1.1418 + * (they should be!) 1.1419 + */ 1.1420 +static CERTCertificate * 1.1421 +pk11_FindCertObjectByRecipientNew(PK11SlotInfo *slot, NSSCMSRecipient **recipientlist, int *rlIndex, void *pwarg) 1.1422 +{ 1.1423 + NSSCMSRecipient *ri = NULL; 1.1424 + int i; 1.1425 + PRBool tokenRescanDone = PR_FALSE; 1.1426 + CERTCertTrust trust; 1.1427 + 1.1428 + for (i=0; (ri = recipientlist[i]) != NULL; i++) { 1.1429 + CERTCertificate *cert = NULL; 1.1430 + if (ri->kind == RLSubjKeyID) { 1.1431 + SECItem *derCert = cert_FindDERCertBySubjectKeyID(ri->id.subjectKeyID); 1.1432 + if (!derCert && !tokenRescanDone) { 1.1433 + /* 1.1434 + * We didn't find the cert by its key ID. If we have slots 1.1435 + * with removable tokens, a failure from 1.1436 + * cert_FindDERCertBySubjectKeyID doesn't necessarily imply 1.1437 + * that the cert is unavailable - the token might simply 1.1438 + * have been inserted after the initial run of 1.1439 + * pk11_keyIDHash_populate (wrapped by PR_CallOnceWithArg), 1.1440 + * or a different token might have been present in that 1.1441 + * slot, initially. Let's check for new tokens... 1.1442 + */ 1.1443 + PK11SlotList *sl = PK11_GetAllTokens(CKM_INVALID_MECHANISM, 1.1444 + PR_FALSE, PR_FALSE, pwarg); 1.1445 + if (sl) { 1.1446 + PK11SlotListElement *le; 1.1447 + SECItem *slotid = SECITEM_AllocItem(NULL, NULL, 1.1448 + sizeof(CK_SLOT_ID) + sizeof(SECMODModuleID)); 1.1449 + if (!slotid) { 1.1450 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1451 + return NULL; 1.1452 + } 1.1453 + for (le = sl->head; le; le = le->next) { 1.1454 + memcpy(slotid->data, &le->slot->slotID, 1.1455 + sizeof(CK_SLOT_ID)); 1.1456 + memcpy(&slotid->data[sizeof(CK_SLOT_ID)], 1.1457 + &le->slot->module->moduleID, 1.1458 + sizeof(SECMODModuleID)); 1.1459 + /* 1.1460 + * Any changes with the slot since our last check? 1.1461 + * If so, re-read the certs in that specific slot. 1.1462 + */ 1.1463 + if (cert_SubjectKeyIDSlotCheckSeries(slotid) 1.1464 + != PK11_GetSlotSeries(le->slot)) { 1.1465 + CERTCertListNode *node = NULL; 1.1466 + SECItem subjKeyID = {siBuffer, NULL, 0}; 1.1467 + CERTCertList *cl = PK11_ListCertsInSlot(le->slot); 1.1468 + if (!cl) { 1.1469 + continue; 1.1470 + } 1.1471 + for (node = CERT_LIST_HEAD(cl); 1.1472 + !CERT_LIST_END(node, cl); 1.1473 + node = CERT_LIST_NEXT(node)) { 1.1474 + if (CERT_IsUserCert(node->cert) && 1.1475 + CERT_FindSubjectKeyIDExtension(node->cert, 1.1476 + &subjKeyID) == SECSuccess) { 1.1477 + if (subjKeyID.data) { 1.1478 + cert_AddSubjectKeyIDMapping(&subjKeyID, 1.1479 + node->cert); 1.1480 + cert_UpdateSubjectKeyIDSlotCheck(slotid, 1.1481 + PK11_GetSlotSeries(le->slot)); 1.1482 + } 1.1483 + SECITEM_FreeItem(&subjKeyID, PR_FALSE); 1.1484 + } 1.1485 + } 1.1486 + CERT_DestroyCertList(cl); 1.1487 + } 1.1488 + } 1.1489 + PK11_FreeSlotList(sl); 1.1490 + SECITEM_FreeItem(slotid, PR_TRUE); 1.1491 + } 1.1492 + /* only check once per message/recipientlist */ 1.1493 + tokenRescanDone = PR_TRUE; 1.1494 + /* do another lookup (hopefully we found that cert...) */ 1.1495 + derCert = cert_FindDERCertBySubjectKeyID(ri->id.subjectKeyID); 1.1496 + } 1.1497 + if (derCert) { 1.1498 + cert = PK11_FindCertFromDERCertItem(slot, derCert, pwarg); 1.1499 + SECITEM_FreeItem(derCert, PR_TRUE); 1.1500 + } 1.1501 + } else { 1.1502 + cert = PK11_FindCertByIssuerAndSNOnToken(slot, ri->id.issuerAndSN, 1.1503 + pwarg); 1.1504 + } 1.1505 + if (cert) { 1.1506 + /* this isn't our cert */ 1.1507 + if (CERT_GetCertTrust(cert, &trust) != SECSuccess || 1.1508 + ((trust.emailFlags & CERTDB_USER) != CERTDB_USER)) { 1.1509 + CERT_DestroyCertificate(cert); 1.1510 + continue; 1.1511 + } 1.1512 + ri->slot = PK11_ReferenceSlot(slot); 1.1513 + *rlIndex = i; 1.1514 + return cert; 1.1515 + } 1.1516 + } 1.1517 + *rlIndex = -1; 1.1518 + return NULL; 1.1519 +} 1.1520 + 1.1521 +/* 1.1522 + * This function is the same as above, but it searches all the slots. 1.1523 + * this is the new version for NSS SMIME code 1.1524 + * this stuff should REALLY be in the SMIME code, but some things in here are not public 1.1525 + * (they should be!) 1.1526 + */ 1.1527 +static CERTCertificate * 1.1528 +pk11_AllFindCertObjectByRecipientNew(NSSCMSRecipient **recipientlist, void *wincx, int *rlIndex) 1.1529 +{ 1.1530 + PK11SlotList *list; 1.1531 + PK11SlotListElement *le; 1.1532 + CERTCertificate *cert = NULL; 1.1533 + SECStatus rv; 1.1534 + 1.1535 + /* get them all! */ 1.1536 + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); 1.1537 + if (list == NULL) { 1.1538 + return CK_INVALID_HANDLE; 1.1539 + } 1.1540 + 1.1541 + /* Look for the slot that holds the Key */ 1.1542 + for (le = list->head ; le; le = le->next) { 1.1543 + rv = pk11_AuthenticateUnfriendly(le->slot, PR_TRUE, wincx); 1.1544 + if (rv != SECSuccess) continue; 1.1545 + 1.1546 + cert = pk11_FindCertObjectByRecipientNew(le->slot, 1.1547 + recipientlist, rlIndex, wincx); 1.1548 + if (cert) 1.1549 + break; 1.1550 + } 1.1551 + 1.1552 + PK11_FreeSlotList(list); 1.1553 + 1.1554 + return cert; 1.1555 +} 1.1556 + 1.1557 +/* 1.1558 + * We're looking for a cert which we have the private key for that's on the 1.1559 + * list of recipients. This searches one slot. 1.1560 + */ 1.1561 +static CERTCertificate * 1.1562 +pk11_FindCertObjectByRecipient(PK11SlotInfo *slot, 1.1563 + SEC_PKCS7RecipientInfo **recipientArray, 1.1564 + SEC_PKCS7RecipientInfo **rip, void *pwarg) 1.1565 +{ 1.1566 + SEC_PKCS7RecipientInfo *ri = NULL; 1.1567 + CERTCertTrust trust; 1.1568 + int i; 1.1569 + 1.1570 + for (i=0; (ri = recipientArray[i]) != NULL; i++) { 1.1571 + CERTCertificate *cert; 1.1572 + 1.1573 + cert = PK11_FindCertByIssuerAndSNOnToken(slot, ri->issuerAndSN, 1.1574 + pwarg); 1.1575 + if (cert) { 1.1576 + /* this isn't our cert */ 1.1577 + if (CERT_GetCertTrust(cert, &trust) != SECSuccess || 1.1578 + ((trust.emailFlags & CERTDB_USER) != CERTDB_USER)) { 1.1579 + CERT_DestroyCertificate(cert); 1.1580 + continue; 1.1581 + } 1.1582 + *rip = ri; 1.1583 + return cert; 1.1584 + } 1.1585 + 1.1586 + } 1.1587 + *rip = NULL; 1.1588 + return NULL; 1.1589 +} 1.1590 + 1.1591 +/* 1.1592 + * This function is the same as above, but it searches all the slots. 1.1593 + */ 1.1594 +static CERTCertificate * 1.1595 +pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, 1.1596 + SEC_PKCS7RecipientInfo **recipientArray,SEC_PKCS7RecipientInfo **rip, 1.1597 + void *wincx) 1.1598 +{ 1.1599 + PK11SlotList *list; 1.1600 + PK11SlotListElement *le; 1.1601 + CERTCertificate * cert = NULL; 1.1602 + PK11SlotInfo *slot = NULL; 1.1603 + SECStatus rv; 1.1604 + 1.1605 + *slotPtr = NULL; 1.1606 + 1.1607 + /* get them all! */ 1.1608 + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); 1.1609 + if (list == NULL) { 1.1610 + return CK_INVALID_HANDLE; 1.1611 + } 1.1612 + 1.1613 + *rip = NULL; 1.1614 + 1.1615 + /* Look for the slot that holds the Key */ 1.1616 + for (le = list->head ; le; le = le->next) { 1.1617 + rv = pk11_AuthenticateUnfriendly(le->slot, PR_TRUE, wincx); 1.1618 + if (rv != SECSuccess) continue; 1.1619 + 1.1620 + cert = pk11_FindCertObjectByRecipient(le->slot, recipientArray, 1.1621 + rip, wincx); 1.1622 + if (cert) { 1.1623 + slot = PK11_ReferenceSlot(le->slot); 1.1624 + break; 1.1625 + } 1.1626 + } 1.1627 + 1.1628 + PK11_FreeSlotList(list); 1.1629 + 1.1630 + if (slot == NULL) { 1.1631 + return NULL; 1.1632 + } 1.1633 + *slotPtr = slot; 1.1634 + PORT_Assert(cert != NULL); 1.1635 + return cert; 1.1636 +} 1.1637 + 1.1638 +/* 1.1639 + * We need to invert the search logic for PKCS 7 because if we search for 1.1640 + * each cert on the list over all the slots, we wind up with lots of spurious 1.1641 + * password prompts. This way we get only one password prompt per slot, at 1.1642 + * the max, and most of the time we can find the cert, and only prompt for 1.1643 + * the key... 1.1644 + */ 1.1645 +CERTCertificate * 1.1646 +PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slotPtr, 1.1647 + SEC_PKCS7RecipientInfo **array, SEC_PKCS7RecipientInfo **rip, 1.1648 + SECKEYPrivateKey**privKey, void *wincx) 1.1649 +{ 1.1650 + CERTCertificate *cert = NULL; 1.1651 + 1.1652 + *privKey = NULL; 1.1653 + *slotPtr = NULL; 1.1654 + cert = pk11_AllFindCertObjectByRecipient(slotPtr,array,rip,wincx); 1.1655 + if (!cert) { 1.1656 + return NULL; 1.1657 + } 1.1658 + 1.1659 + *privKey = PK11_FindKeyByAnyCert(cert, wincx); 1.1660 + if (*privKey == NULL) { 1.1661 + goto loser; 1.1662 + } 1.1663 + 1.1664 + return cert; 1.1665 +loser: 1.1666 + if (cert) CERT_DestroyCertificate(cert); 1.1667 + if (*slotPtr) PK11_FreeSlot(*slotPtr); 1.1668 + *slotPtr = NULL; 1.1669 + return NULL; 1.1670 +} 1.1671 + 1.1672 +/* 1.1673 + * This is the new version of the above function for NSS SMIME code 1.1674 + * this stuff should REALLY be in the SMIME code, but some things in here are not public 1.1675 + * (they should be!) 1.1676 + */ 1.1677 +int 1.1678 +PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient **recipientlist, void *wincx) 1.1679 +{ 1.1680 + CERTCertificate *cert; 1.1681 + NSSCMSRecipient *rl; 1.1682 + PRStatus rv; 1.1683 + int rlIndex; 1.1684 + 1.1685 + rv = PR_CallOnceWithArg(&keyIDHashCallOnce, pk11_keyIDHash_populate, wincx); 1.1686 + if (rv != PR_SUCCESS) 1.1687 + return -1; 1.1688 + 1.1689 + cert = pk11_AllFindCertObjectByRecipientNew(recipientlist, wincx, &rlIndex); 1.1690 + if (!cert) { 1.1691 + return -1; 1.1692 + } 1.1693 + 1.1694 + rl = recipientlist[rlIndex]; 1.1695 + 1.1696 + /* at this point, rl->slot is set */ 1.1697 + 1.1698 + rl->privkey = PK11_FindKeyByAnyCert(cert, wincx); 1.1699 + if (rl->privkey == NULL) { 1.1700 + goto loser; 1.1701 + } 1.1702 + 1.1703 + /* make a cert from the cert handle */ 1.1704 + rl->cert = cert; 1.1705 + return rlIndex; 1.1706 + 1.1707 +loser: 1.1708 + if (cert) CERT_DestroyCertificate(cert); 1.1709 + if (rl->slot) PK11_FreeSlot(rl->slot); 1.1710 + rl->slot = NULL; 1.1711 + return -1; 1.1712 +} 1.1713 + 1.1714 +CERTCertificate * 1.1715 +PK11_FindCertByIssuerAndSN(PK11SlotInfo **slotPtr, CERTIssuerAndSN *issuerSN, 1.1716 + void *wincx) 1.1717 +{ 1.1718 + CERTCertificate *rvCert = NULL; 1.1719 + NSSCertificate *cert; 1.1720 + NSSDER issuer, serial; 1.1721 + NSSCryptoContext *cc; 1.1722 + SECItem *derSerial; 1.1723 + 1.1724 + if (!issuerSN || !issuerSN->derIssuer.data || !issuerSN->derIssuer.len || 1.1725 + !issuerSN->serialNumber.data || !issuerSN->serialNumber.len || 1.1726 + issuerSN->derIssuer.len > CERT_MAX_DN_BYTES || 1.1727 + issuerSN->serialNumber.len > CERT_MAX_SERIAL_NUMBER_BYTES ) { 1.1728 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1729 + return NULL; 1.1730 + } 1.1731 + 1.1732 + if (slotPtr) *slotPtr = NULL; 1.1733 + 1.1734 + /* PKCS#11 needs to use DER-encoded serial numbers. Create a 1.1735 + * CERTIssuerAndSN that actually has the encoded value and pass that 1.1736 + * to PKCS#11 (and the crypto context). 1.1737 + */ 1.1738 + derSerial = SEC_ASN1EncodeItem(NULL, NULL, 1.1739 + &issuerSN->serialNumber, 1.1740 + SEC_ASN1_GET(SEC_IntegerTemplate)); 1.1741 + if (!derSerial) { 1.1742 + return NULL; 1.1743 + } 1.1744 + 1.1745 + NSSITEM_FROM_SECITEM(&issuer, &issuerSN->derIssuer); 1.1746 + NSSITEM_FROM_SECITEM(&serial, derSerial); 1.1747 + 1.1748 + cc = STAN_GetDefaultCryptoContext(); 1.1749 + cert = NSSCryptoContext_FindCertificateByIssuerAndSerialNumber(cc, 1.1750 + &issuer, 1.1751 + &serial); 1.1752 + if (cert) { 1.1753 + SECITEM_FreeItem(derSerial, PR_TRUE); 1.1754 + return STAN_GetCERTCertificateOrRelease(cert); 1.1755 + } 1.1756 + 1.1757 + do { 1.1758 + /* free the old cert on retry. Associated slot was not present */ 1.1759 + if (rvCert) { 1.1760 + CERT_DestroyCertificate(rvCert); 1.1761 + rvCert = NULL; 1.1762 + } 1.1763 + 1.1764 + cert = NSSTrustDomain_FindCertificateByIssuerAndSerialNumber( 1.1765 + STAN_GetDefaultTrustDomain(), 1.1766 + &issuer, 1.1767 + &serial); 1.1768 + if (!cert) { 1.1769 + break; 1.1770 + } 1.1771 + 1.1772 + rvCert = STAN_GetCERTCertificateOrRelease(cert); 1.1773 + if (rvCert == NULL) { 1.1774 + break; 1.1775 + } 1.1776 + 1.1777 + /* Check to see if the cert's token is still there */ 1.1778 + } while (!PK11_IsPresent(rvCert->slot)); 1.1779 + 1.1780 + if (rvCert && slotPtr) *slotPtr = PK11_ReferenceSlot(rvCert->slot); 1.1781 + 1.1782 + SECITEM_FreeItem(derSerial, PR_TRUE); 1.1783 + return rvCert; 1.1784 +} 1.1785 + 1.1786 +CK_OBJECT_HANDLE 1.1787 +PK11_FindObjectForCert(CERTCertificate *cert, void *wincx, PK11SlotInfo **pSlot) 1.1788 +{ 1.1789 + CK_OBJECT_HANDLE certHandle; 1.1790 + CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; 1.1791 + CK_ATTRIBUTE *attr; 1.1792 + CK_ATTRIBUTE searchTemplate[]= { 1.1793 + { CKA_CLASS, NULL, 0 }, 1.1794 + { CKA_VALUE, NULL, 0 }, 1.1795 + }; 1.1796 + int templateSize = sizeof(searchTemplate)/sizeof(searchTemplate[0]); 1.1797 + 1.1798 + attr = searchTemplate; 1.1799 + PK11_SETATTRS(attr, CKA_CLASS, &certClass, sizeof(certClass)); attr++; 1.1800 + PK11_SETATTRS(attr, CKA_VALUE, cert->derCert.data, cert->derCert.len); 1.1801 + 1.1802 + if (cert->slot) { 1.1803 + certHandle = pk11_getcerthandle(cert->slot, cert, searchTemplate, 1.1804 + templateSize); 1.1805 + if (certHandle != CK_INVALID_HANDLE) { 1.1806 + *pSlot = PK11_ReferenceSlot(cert->slot); 1.1807 + return certHandle; 1.1808 + } 1.1809 + } 1.1810 + 1.1811 + certHandle = pk11_FindCertObjectByTemplate(pSlot, searchTemplate, 1.1812 + templateSize, wincx); 1.1813 + if (certHandle != CK_INVALID_HANDLE) { 1.1814 + if (cert->slot == NULL) { 1.1815 + cert->slot = PK11_ReferenceSlot(*pSlot); 1.1816 + cert->pkcs11ID = certHandle; 1.1817 + cert->ownSlot = PR_TRUE; 1.1818 + cert->series = cert->slot->series; 1.1819 + } 1.1820 + } 1.1821 + 1.1822 + return(certHandle); 1.1823 +} 1.1824 + 1.1825 +SECKEYPrivateKey * 1.1826 +PK11_FindKeyByAnyCert(CERTCertificate *cert, void *wincx) 1.1827 +{ 1.1828 + CK_OBJECT_HANDLE certHandle; 1.1829 + CK_OBJECT_HANDLE keyHandle; 1.1830 + PK11SlotInfo *slot = NULL; 1.1831 + SECKEYPrivateKey *privKey = NULL; 1.1832 + PRBool needLogin; 1.1833 + SECStatus rv; 1.1834 + int err; 1.1835 + 1.1836 + certHandle = PK11_FindObjectForCert(cert, wincx, &slot); 1.1837 + if (certHandle == CK_INVALID_HANDLE) { 1.1838 + return NULL; 1.1839 + } 1.1840 + /* 1.1841 + * prevent a login race condition. If slot is logged in between 1.1842 + * our call to pk11_LoginStillRequired and the 1.1843 + * PK11_MatchItem. The matchItem call will either succeed, or 1.1844 + * we will call it one more time after calling PK11_Authenticate 1.1845 + * (which is a noop on an authenticated token). 1.1846 + */ 1.1847 + needLogin = pk11_LoginStillRequired(slot,wincx); 1.1848 + keyHandle = PK11_MatchItem(slot,certHandle,CKO_PRIVATE_KEY); 1.1849 + if ((keyHandle == CK_INVALID_HANDLE) && needLogin && 1.1850 + (SSL_ERROR_NO_CERTIFICATE == (err = PORT_GetError()) || 1.1851 + SEC_ERROR_TOKEN_NOT_LOGGED_IN == err ) ) { 1.1852 + /* authenticate and try again */ 1.1853 + rv = PK11_Authenticate(slot, PR_TRUE, wincx); 1.1854 + if (rv == SECSuccess) { 1.1855 + keyHandle = PK11_MatchItem(slot,certHandle,CKO_PRIVATE_KEY); 1.1856 + } 1.1857 + } 1.1858 + if (keyHandle != CK_INVALID_HANDLE) { 1.1859 + privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx); 1.1860 + } 1.1861 + if (slot) { 1.1862 + PK11_FreeSlot(slot); 1.1863 + } 1.1864 + return privKey; 1.1865 +} 1.1866 + 1.1867 +CK_OBJECT_HANDLE 1.1868 +pk11_FindPubKeyByAnyCert(CERTCertificate *cert, PK11SlotInfo **slot, void *wincx) 1.1869 +{ 1.1870 + CK_OBJECT_HANDLE certHandle; 1.1871 + CK_OBJECT_HANDLE keyHandle; 1.1872 + 1.1873 + certHandle = PK11_FindObjectForCert(cert, wincx, slot); 1.1874 + if (certHandle == CK_INVALID_HANDLE) { 1.1875 + return CK_INVALID_HANDLE; 1.1876 + } 1.1877 + keyHandle = PK11_MatchItem(*slot,certHandle,CKO_PUBLIC_KEY); 1.1878 + if (keyHandle == CK_INVALID_HANDLE) { 1.1879 + PK11_FreeSlot(*slot); 1.1880 + return CK_INVALID_HANDLE; 1.1881 + } 1.1882 + return keyHandle; 1.1883 +} 1.1884 + 1.1885 +/* 1.1886 + * find the number of certs in the slot with the same subject name 1.1887 + */ 1.1888 +int 1.1889 +PK11_NumberCertsForCertSubject(CERTCertificate *cert) 1.1890 +{ 1.1891 + CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; 1.1892 + CK_ATTRIBUTE theTemplate[] = { 1.1893 + { CKA_CLASS, NULL, 0 }, 1.1894 + { CKA_SUBJECT, NULL, 0 }, 1.1895 + }; 1.1896 + CK_ATTRIBUTE *attr = theTemplate; 1.1897 + int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]); 1.1898 + 1.1899 + PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; 1.1900 + PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len); 1.1901 + 1.1902 + if (cert->slot == NULL) { 1.1903 + PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, 1.1904 + PR_FALSE,PR_TRUE,NULL); 1.1905 + PK11SlotListElement *le; 1.1906 + int count = 0; 1.1907 + 1.1908 + if (!list) { 1.1909 + /* error code is set */ 1.1910 + return 0; 1.1911 + } 1.1912 + 1.1913 + /* loop through all the fortezza tokens */ 1.1914 + for (le = list->head; le; le = le->next) { 1.1915 + count += PK11_NumberObjectsFor(le->slot,theTemplate,templateSize); 1.1916 + } 1.1917 + PK11_FreeSlotList(list); 1.1918 + return count; 1.1919 + } 1.1920 + 1.1921 + return PK11_NumberObjectsFor(cert->slot,theTemplate,templateSize); 1.1922 +} 1.1923 + 1.1924 +/* 1.1925 + * Walk all the certs with the same subject 1.1926 + */ 1.1927 +SECStatus 1.1928 +PK11_TraverseCertsForSubject(CERTCertificate *cert, 1.1929 + SECStatus(* callback)(CERTCertificate*, void *), void *arg) 1.1930 +{ 1.1931 + if(!cert) { 1.1932 + return SECFailure; 1.1933 + } 1.1934 + if (cert->slot == NULL) { 1.1935 + PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, 1.1936 + PR_FALSE,PR_TRUE,NULL); 1.1937 + PK11SlotListElement *le; 1.1938 + 1.1939 + if (!list) { 1.1940 + /* error code is set */ 1.1941 + return SECFailure; 1.1942 + } 1.1943 + /* loop through all the tokens */ 1.1944 + for (le = list->head; le; le = le->next) { 1.1945 + PK11_TraverseCertsForSubjectInSlot(cert,le->slot,callback,arg); 1.1946 + } 1.1947 + PK11_FreeSlotList(list); 1.1948 + return SECSuccess; 1.1949 + 1.1950 + } 1.1951 + 1.1952 + return PK11_TraverseCertsForSubjectInSlot(cert, cert->slot, callback, arg); 1.1953 +} 1.1954 + 1.1955 +SECStatus 1.1956 +PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, 1.1957 + SECStatus(* callback)(CERTCertificate*, void *), void *arg) 1.1958 +{ 1.1959 + PRStatus nssrv = PR_SUCCESS; 1.1960 + NSSToken *token; 1.1961 + NSSDER subject; 1.1962 + NSSTrustDomain *td; 1.1963 + nssList *subjectList; 1.1964 + nssPKIObjectCollection *collection; 1.1965 + nssCryptokiObject **instances; 1.1966 + NSSCertificate **certs; 1.1967 + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; 1.1968 + td = STAN_GetDefaultTrustDomain(); 1.1969 + NSSITEM_FROM_SECITEM(&subject, &cert->derSubject); 1.1970 + token = PK11Slot_GetNSSToken(slot); 1.1971 + if (!nssToken_IsPresent(token)) { 1.1972 + return SECSuccess; 1.1973 + } 1.1974 + collection = nssCertificateCollection_Create(td, NULL); 1.1975 + if (!collection) { 1.1976 + return SECFailure; 1.1977 + } 1.1978 + subjectList = nssList_Create(NULL, PR_FALSE); 1.1979 + if (!subjectList) { 1.1980 + nssPKIObjectCollection_Destroy(collection); 1.1981 + return SECFailure; 1.1982 + } 1.1983 + (void)nssTrustDomain_GetCertsForSubjectFromCache(td, &subject, 1.1984 + subjectList); 1.1985 + transfer_token_certs_to_collection(subjectList, token, collection); 1.1986 + instances = nssToken_FindCertificatesBySubject(token, NULL, 1.1987 + &subject, 1.1988 + tokenOnly, 0, &nssrv); 1.1989 + nssPKIObjectCollection_AddInstances(collection, instances, 0); 1.1990 + nss_ZFreeIf(instances); 1.1991 + nssList_Destroy(subjectList); 1.1992 + certs = nssPKIObjectCollection_GetCertificates(collection, 1.1993 + NULL, 0, NULL); 1.1994 + nssPKIObjectCollection_Destroy(collection); 1.1995 + if (certs) { 1.1996 + CERTCertificate *oldie; 1.1997 + NSSCertificate **cp; 1.1998 + for (cp = certs; *cp; cp++) { 1.1999 + oldie = STAN_GetCERTCertificate(*cp); 1.2000 + if (!oldie) { 1.2001 + continue; 1.2002 + } 1.2003 + if ((*callback)(oldie, arg) != SECSuccess) { 1.2004 + nssrv = PR_FAILURE; 1.2005 + break; 1.2006 + } 1.2007 + } 1.2008 + nssCertificateArray_Destroy(certs); 1.2009 + } 1.2010 + return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; 1.2011 +} 1.2012 + 1.2013 +SECStatus 1.2014 +PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, 1.2015 + SECStatus(* callback)(CERTCertificate*, void *), void *arg) 1.2016 +{ 1.2017 + struct nss3_cert_cbstr pk11cb; 1.2018 + PRStatus nssrv = PR_SUCCESS; 1.2019 + NSSToken *token; 1.2020 + NSSTrustDomain *td; 1.2021 + NSSUTF8 *nick; 1.2022 + PRBool created = PR_FALSE; 1.2023 + nssCryptokiObject **instances; 1.2024 + nssPKIObjectCollection *collection = NULL; 1.2025 + NSSCertificate **certs; 1.2026 + nssList *nameList = NULL; 1.2027 + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; 1.2028 + pk11cb.callback = callback; 1.2029 + pk11cb.arg = arg; 1.2030 + token = PK11Slot_GetNSSToken(slot); 1.2031 + if (!nssToken_IsPresent(token)) { 1.2032 + return SECSuccess; 1.2033 + } 1.2034 + if (nickname->data[nickname->len-1] != '\0') { 1.2035 + nick = nssUTF8_Create(NULL, nssStringType_UTF8String, 1.2036 + nickname->data, nickname->len); 1.2037 + created = PR_TRUE; 1.2038 + } else { 1.2039 + nick = (NSSUTF8 *)nickname->data; 1.2040 + } 1.2041 + td = STAN_GetDefaultTrustDomain(); 1.2042 + collection = nssCertificateCollection_Create(td, NULL); 1.2043 + if (!collection) { 1.2044 + goto loser; 1.2045 + } 1.2046 + nameList = nssList_Create(NULL, PR_FALSE); 1.2047 + if (!nameList) { 1.2048 + goto loser; 1.2049 + } 1.2050 + (void)nssTrustDomain_GetCertsForNicknameFromCache(td, nick, nameList); 1.2051 + transfer_token_certs_to_collection(nameList, token, collection); 1.2052 + instances = nssToken_FindCertificatesByNickname(token, NULL, 1.2053 + nick, 1.2054 + tokenOnly, 0, &nssrv); 1.2055 + nssPKIObjectCollection_AddInstances(collection, instances, 0); 1.2056 + nss_ZFreeIf(instances); 1.2057 + nssList_Destroy(nameList); 1.2058 + certs = nssPKIObjectCollection_GetCertificates(collection, 1.2059 + NULL, 0, NULL); 1.2060 + nssPKIObjectCollection_Destroy(collection); 1.2061 + if (certs) { 1.2062 + CERTCertificate *oldie; 1.2063 + NSSCertificate **cp; 1.2064 + for (cp = certs; *cp; cp++) { 1.2065 + oldie = STAN_GetCERTCertificate(*cp); 1.2066 + if (!oldie) { 1.2067 + continue; 1.2068 + } 1.2069 + if ((*callback)(oldie, arg) != SECSuccess) { 1.2070 + nssrv = PR_FAILURE; 1.2071 + break; 1.2072 + } 1.2073 + } 1.2074 + nssCertificateArray_Destroy(certs); 1.2075 + } 1.2076 + if (created) nss_ZFreeIf(nick); 1.2077 + return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; 1.2078 +loser: 1.2079 + if (created) { 1.2080 + nss_ZFreeIf(nick); 1.2081 + } 1.2082 + if (collection) { 1.2083 + nssPKIObjectCollection_Destroy(collection); 1.2084 + } 1.2085 + if (nameList) { 1.2086 + nssList_Destroy(nameList); 1.2087 + } 1.2088 + return SECFailure; 1.2089 +} 1.2090 + 1.2091 +SECStatus 1.2092 +PK11_TraverseCertsInSlot(PK11SlotInfo *slot, 1.2093 + SECStatus(* callback)(CERTCertificate*, void *), void *arg) 1.2094 +{ 1.2095 + PRStatus nssrv; 1.2096 + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); 1.2097 + NSSToken *tok; 1.2098 + nssList *certList = NULL; 1.2099 + nssCryptokiObject **instances; 1.2100 + nssPKIObjectCollection *collection; 1.2101 + NSSCertificate **certs; 1.2102 + nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; 1.2103 + tok = PK11Slot_GetNSSToken(slot); 1.2104 + if (!nssToken_IsPresent(tok)) { 1.2105 + return SECSuccess; 1.2106 + } 1.2107 + collection = nssCertificateCollection_Create(td, NULL); 1.2108 + if (!collection) { 1.2109 + return SECFailure; 1.2110 + } 1.2111 + certList = nssList_Create(NULL, PR_FALSE); 1.2112 + if (!certList) { 1.2113 + nssPKIObjectCollection_Destroy(collection); 1.2114 + return SECFailure; 1.2115 + } 1.2116 + (void)nssTrustDomain_GetCertsFromCache(td, certList); 1.2117 + transfer_token_certs_to_collection(certList, tok, collection); 1.2118 + instances = nssToken_FindObjects(tok, NULL, CKO_CERTIFICATE, 1.2119 + tokenOnly, 0, &nssrv); 1.2120 + nssPKIObjectCollection_AddInstances(collection, instances, 0); 1.2121 + nss_ZFreeIf(instances); 1.2122 + nssList_Destroy(certList); 1.2123 + certs = nssPKIObjectCollection_GetCertificates(collection, 1.2124 + NULL, 0, NULL); 1.2125 + nssPKIObjectCollection_Destroy(collection); 1.2126 + if (certs) { 1.2127 + CERTCertificate *oldie; 1.2128 + NSSCertificate **cp; 1.2129 + for (cp = certs; *cp; cp++) { 1.2130 + oldie = STAN_GetCERTCertificate(*cp); 1.2131 + if (!oldie) { 1.2132 + continue; 1.2133 + } 1.2134 + if ((*callback)(oldie, arg) != SECSuccess) { 1.2135 + nssrv = PR_FAILURE; 1.2136 + break; 1.2137 + } 1.2138 + } 1.2139 + nssCertificateArray_Destroy(certs); 1.2140 + } 1.2141 + return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; 1.2142 +} 1.2143 + 1.2144 +/* 1.2145 + * return the certificate associated with a derCert 1.2146 + */ 1.2147 +CERTCertificate * 1.2148 +PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert, 1.2149 + void *wincx) 1.2150 +{ 1.2151 + return PK11_FindCertFromDERCertItem(slot, &cert->derCert, wincx); 1.2152 +} 1.2153 + 1.2154 +CERTCertificate * 1.2155 +PK11_FindCertFromDERCertItem(PK11SlotInfo *slot, const SECItem *inDerCert, 1.2156 + void *wincx) 1.2157 + 1.2158 +{ 1.2159 + NSSDER derCert; 1.2160 + NSSToken *tok; 1.2161 + NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); 1.2162 + nssCryptokiObject *co = NULL; 1.2163 + SECStatus rv; 1.2164 + 1.2165 + tok = PK11Slot_GetNSSToken(slot); 1.2166 + NSSITEM_FROM_SECITEM(&derCert, inDerCert); 1.2167 + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); 1.2168 + if (rv != SECSuccess) { 1.2169 + PK11_FreeSlot(slot); 1.2170 + return NULL; 1.2171 + } 1.2172 + 1.2173 + co = nssToken_FindCertificateByEncodedCertificate(tok, NULL, &derCert, 1.2174 + nssTokenSearchType_TokenOnly, NULL); 1.2175 + 1.2176 + return co ? PK11_MakeCertFromHandle(slot, co->handle, NULL) : NULL; 1.2177 + 1.2178 +} 1.2179 + 1.2180 +/* 1.2181 + * import a cert for a private key we have already generated. Set the label 1.2182 + * on both to be the nickname. 1.2183 + */ 1.2184 +static CK_OBJECT_HANDLE 1.2185 +pk11_findKeyObjectByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, 1.2186 + void *wincx) 1.2187 +{ 1.2188 + SECItem *keyID; 1.2189 + CK_OBJECT_HANDLE key; 1.2190 + SECStatus rv; 1.2191 + PRBool needLogin; 1.2192 + int err; 1.2193 + 1.2194 + if((slot == NULL) || (cert == NULL)) { 1.2195 + return CK_INVALID_HANDLE; 1.2196 + } 1.2197 + 1.2198 + keyID = pk11_mkcertKeyID(cert); 1.2199 + if(keyID == NULL) { 1.2200 + return CK_INVALID_HANDLE; 1.2201 + } 1.2202 + 1.2203 + /* 1.2204 + * prevent a login race condition. If slot is logged in between 1.2205 + * our call to pk11_LoginStillRequired and the 1.2206 + * pk11_FindPrivateKeyFromCerID. The matchItem call will either succeed, or 1.2207 + * we will call it one more time after calling PK11_Authenticate 1.2208 + * (which is a noop on an authenticated token). 1.2209 + */ 1.2210 + needLogin = pk11_LoginStillRequired(slot,wincx); 1.2211 + key = pk11_FindPrivateKeyFromCertID(slot, keyID); 1.2212 + if ((key == CK_INVALID_HANDLE) && needLogin && 1.2213 + (SSL_ERROR_NO_CERTIFICATE == (err = PORT_GetError()) || 1.2214 + SEC_ERROR_TOKEN_NOT_LOGGED_IN == err )) { 1.2215 + /* authenticate and try again */ 1.2216 + rv = PK11_Authenticate(slot, PR_TRUE, wincx); 1.2217 + if (rv != SECSuccess) goto loser; 1.2218 + key = pk11_FindPrivateKeyFromCertID(slot, keyID); 1.2219 + } 1.2220 + 1.2221 +loser: 1.2222 + SECITEM_ZfreeItem(keyID, PR_TRUE); 1.2223 + return key; 1.2224 +} 1.2225 + 1.2226 +SECKEYPrivateKey * 1.2227 +PK11_FindKeyByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, 1.2228 + void *wincx) 1.2229 +{ 1.2230 + CK_OBJECT_HANDLE keyHandle; 1.2231 + 1.2232 + if((slot == NULL) || (cert == NULL)) { 1.2233 + return NULL; 1.2234 + } 1.2235 + 1.2236 + keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx); 1.2237 + if (keyHandle == CK_INVALID_HANDLE) { 1.2238 + return NULL; 1.2239 + } 1.2240 + 1.2241 + return PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,wincx); 1.2242 +} 1.2243 + 1.2244 +SECStatus 1.2245 +PK11_ImportCertForKeyToSlot(PK11SlotInfo *slot, CERTCertificate *cert, 1.2246 + char *nickname, 1.2247 + PRBool addCertUsage,void *wincx) 1.2248 +{ 1.2249 + CK_OBJECT_HANDLE keyHandle; 1.2250 + 1.2251 + if((slot == NULL) || (cert == NULL) || (nickname == NULL)) { 1.2252 + return SECFailure; 1.2253 + } 1.2254 + 1.2255 + keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx); 1.2256 + if (keyHandle == CK_INVALID_HANDLE) { 1.2257 + return SECFailure; 1.2258 + } 1.2259 + 1.2260 + return PK11_ImportCert(slot, cert, keyHandle, nickname, addCertUsage); 1.2261 +} 1.2262 + 1.2263 + 1.2264 +/* remove when the real version comes out */ 1.2265 +#define SEC_OID_MISSI_KEA 300 /* until we have v3 stuff merged */ 1.2266 +PRBool 1.2267 +KEAPQGCompare(CERTCertificate *server,CERTCertificate *cert) { 1.2268 + 1.2269 + /* not implemented */ 1.2270 + return PR_FALSE; 1.2271 +} 1.2272 + 1.2273 +PRBool 1.2274 +PK11_FortezzaHasKEA(CERTCertificate *cert) 1.2275 +{ 1.2276 + /* look at the subject and see if it is a KEA for MISSI key */ 1.2277 + SECOidData *oid; 1.2278 + CERTCertTrust trust; 1.2279 + 1.2280 + if (CERT_GetCertTrust(cert, &trust) != SECSuccess || 1.2281 + ((trust.sslFlags & CERTDB_USER) != CERTDB_USER)) { 1.2282 + return PR_FALSE; 1.2283 + } 1.2284 + 1.2285 + oid = SECOID_FindOID(&cert->subjectPublicKeyInfo.algorithm.algorithm); 1.2286 + if (!oid) { 1.2287 + return PR_FALSE; 1.2288 + } 1.2289 + 1.2290 + return (PRBool)((oid->offset == SEC_OID_MISSI_KEA_DSS_OLD) || 1.2291 + (oid->offset == SEC_OID_MISSI_KEA_DSS) || 1.2292 + (oid->offset == SEC_OID_MISSI_KEA)) ; 1.2293 +} 1.2294 + 1.2295 +/* 1.2296 + * Find a kea cert on this slot that matches the domain of it's peer 1.2297 + */ 1.2298 +static CERTCertificate 1.2299 +*pk11_GetKEAMate(PK11SlotInfo *slot,CERTCertificate *peer) 1.2300 +{ 1.2301 + int i; 1.2302 + CERTCertificate *returnedCert = NULL; 1.2303 + 1.2304 + for (i=0; i < slot->cert_count; i++) { 1.2305 + CERTCertificate *cert = slot->cert_array[i]; 1.2306 + 1.2307 + if (PK11_FortezzaHasKEA(cert) && KEAPQGCompare(peer,cert)) { 1.2308 + returnedCert = CERT_DupCertificate(cert); 1.2309 + break; 1.2310 + } 1.2311 + } 1.2312 + return returnedCert; 1.2313 +} 1.2314 + 1.2315 +/* 1.2316 + * The following is a FORTEZZA only Certificate request. We call this when we 1.2317 + * are doing a non-client auth SSL connection. We are only interested in the 1.2318 + * fortezza slots, and we are only interested in certs that share the same root 1.2319 + * key as the server. 1.2320 + */ 1.2321 +CERTCertificate * 1.2322 +PK11_FindBestKEAMatch(CERTCertificate *server, void *wincx) 1.2323 +{ 1.2324 + PK11SlotList *keaList = PK11_GetAllTokens(CKM_KEA_KEY_DERIVE, 1.2325 + PR_FALSE,PR_TRUE,wincx); 1.2326 + PK11SlotListElement *le; 1.2327 + CERTCertificate *returnedCert = NULL; 1.2328 + SECStatus rv; 1.2329 + 1.2330 + if (!keaList) { 1.2331 + /* error code is set */ 1.2332 + return NULL; 1.2333 + } 1.2334 + 1.2335 + /* loop through all the fortezza tokens */ 1.2336 + for (le = keaList->head; le; le = le->next) { 1.2337 + rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); 1.2338 + if (rv != SECSuccess) continue; 1.2339 + if (le->slot->session == CK_INVALID_SESSION) { 1.2340 + continue; 1.2341 + } 1.2342 + returnedCert = pk11_GetKEAMate(le->slot,server); 1.2343 + if (returnedCert) break; 1.2344 + } 1.2345 + PK11_FreeSlotList(keaList); 1.2346 + 1.2347 + return returnedCert; 1.2348 +} 1.2349 + 1.2350 +/* 1.2351 + * find a matched pair of kea certs to key exchange parameters from one 1.2352 + * fortezza card to another as necessary. 1.2353 + */ 1.2354 +SECStatus 1.2355 +PK11_GetKEAMatchedCerts(PK11SlotInfo *slot1, PK11SlotInfo *slot2, 1.2356 + CERTCertificate **cert1, CERTCertificate **cert2) 1.2357 +{ 1.2358 + CERTCertificate *returnedCert = NULL; 1.2359 + int i; 1.2360 + 1.2361 + for (i=0; i < slot1->cert_count; i++) { 1.2362 + CERTCertificate *cert = slot1->cert_array[i]; 1.2363 + 1.2364 + if (PK11_FortezzaHasKEA(cert)) { 1.2365 + returnedCert = pk11_GetKEAMate(slot2,cert); 1.2366 + if (returnedCert != NULL) { 1.2367 + *cert2 = returnedCert; 1.2368 + *cert1 = CERT_DupCertificate(cert); 1.2369 + return SECSuccess; 1.2370 + } 1.2371 + } 1.2372 + } 1.2373 + return SECFailure; 1.2374 +} 1.2375 + 1.2376 +/* 1.2377 + * return the private key From a given Cert 1.2378 + */ 1.2379 +CK_OBJECT_HANDLE 1.2380 +PK11_FindCertInSlot(PK11SlotInfo *slot, CERTCertificate *cert, void *wincx) 1.2381 +{ 1.2382 + CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; 1.2383 + CK_ATTRIBUTE theTemplate[] = { 1.2384 + { CKA_VALUE, NULL, 0 }, 1.2385 + { CKA_CLASS, NULL, 0 } 1.2386 + }; 1.2387 + /* if you change the array, change the variable below as well */ 1.2388 + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); 1.2389 + CK_ATTRIBUTE *attrs = theTemplate; 1.2390 + SECStatus rv; 1.2391 + 1.2392 + PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, 1.2393 + cert->derCert.len); attrs++; 1.2394 + PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); 1.2395 + 1.2396 + /* 1.2397 + * issue the find 1.2398 + */ 1.2399 + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); 1.2400 + if (rv != SECSuccess) { 1.2401 + return CK_INVALID_HANDLE; 1.2402 + } 1.2403 + 1.2404 + return pk11_getcerthandle(slot,cert,theTemplate,tsize); 1.2405 +} 1.2406 + 1.2407 +/* Looking for PK11_GetKeyIDFromCert? 1.2408 + * Use PK11_GetLowLevelKeyIDForCert instead. 1.2409 + */ 1.2410 + 1.2411 + 1.2412 +struct listCertsStr { 1.2413 + PK11CertListType type; 1.2414 + CERTCertList *certList; 1.2415 +}; 1.2416 + 1.2417 +static PRStatus 1.2418 +pk11ListCertCallback(NSSCertificate *c, void *arg) 1.2419 +{ 1.2420 + struct listCertsStr *listCertP = (struct listCertsStr *)arg; 1.2421 + CERTCertificate *newCert = NULL; 1.2422 + PK11CertListType type = listCertP->type; 1.2423 + CERTCertList *certList = listCertP->certList; 1.2424 + PRBool isUnique = PR_FALSE; 1.2425 + PRBool isCA = PR_FALSE; 1.2426 + char *nickname = NULL; 1.2427 + unsigned int certType; 1.2428 + SECStatus rv; 1.2429 + 1.2430 + if ((type == PK11CertListUnique) || (type == PK11CertListRootUnique) || 1.2431 + (type == PK11CertListCAUnique) || (type == PK11CertListUserUnique) ) { 1.2432 + /* only list one instance of each certificate, even if several exist */ 1.2433 + isUnique = PR_TRUE; 1.2434 + } 1.2435 + if ((type == PK11CertListCA) || (type == PK11CertListRootUnique) || 1.2436 + (type == PK11CertListCAUnique)) { 1.2437 + isCA = PR_TRUE; 1.2438 + } 1.2439 + 1.2440 + /* if we want user certs and we don't have one skip this cert */ 1.2441 + if ( ( (type == PK11CertListUser) || (type == PK11CertListUserUnique) ) && 1.2442 + !NSSCertificate_IsPrivateKeyAvailable(c, NULL,NULL)) { 1.2443 + return PR_SUCCESS; 1.2444 + } 1.2445 + 1.2446 + /* PK11CertListRootUnique means we want CA certs without a private key. 1.2447 + * This is for legacy app support . PK11CertListCAUnique should be used 1.2448 + * instead to get all CA certs, regardless of private key 1.2449 + */ 1.2450 + if ((type == PK11CertListRootUnique) && 1.2451 + NSSCertificate_IsPrivateKeyAvailable(c, NULL,NULL)) { 1.2452 + return PR_SUCCESS; 1.2453 + } 1.2454 + 1.2455 + /* caller still owns the reference to 'c' */ 1.2456 + newCert = STAN_GetCERTCertificate(c); 1.2457 + if (!newCert) { 1.2458 + return PR_SUCCESS; 1.2459 + } 1.2460 + /* if we want CA certs and it ain't one, skip it */ 1.2461 + if( isCA && (!CERT_IsCACert(newCert, &certType)) ) { 1.2462 + return PR_SUCCESS; 1.2463 + } 1.2464 + if (isUnique) { 1.2465 + CERT_DupCertificate(newCert); 1.2466 + 1.2467 + nickname = STAN_GetCERTCertificateName(certList->arena, c); 1.2468 + 1.2469 + /* put slot certs at the end */ 1.2470 + if (newCert->slot && !PK11_IsInternal(newCert->slot)) { 1.2471 + rv = CERT_AddCertToListTailWithData(certList,newCert,nickname); 1.2472 + } else { 1.2473 + rv = CERT_AddCertToListHeadWithData(certList,newCert,nickname); 1.2474 + } 1.2475 + /* if we didn't add the cert to the list, don't leak it */ 1.2476 + if (rv != SECSuccess) { 1.2477 + CERT_DestroyCertificate(newCert); 1.2478 + } 1.2479 + } else { 1.2480 + /* add multiple instances to the cert list */ 1.2481 + nssCryptokiObject **ip; 1.2482 + nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object); 1.2483 + if (!instances) { 1.2484 + return PR_SUCCESS; 1.2485 + } 1.2486 + for (ip = instances; *ip; ip++) { 1.2487 + nssCryptokiObject *instance = *ip; 1.2488 + PK11SlotInfo *slot = instance->token->pk11slot; 1.2489 + 1.2490 + /* put the same CERTCertificate in the list for all instances */ 1.2491 + CERT_DupCertificate(newCert); 1.2492 + 1.2493 + nickname = STAN_GetCERTCertificateNameForInstance( 1.2494 + certList->arena, c, instance); 1.2495 + 1.2496 + /* put slot certs at the end */ 1.2497 + if (slot && !PK11_IsInternal(slot)) { 1.2498 + rv = CERT_AddCertToListTailWithData(certList,newCert,nickname); 1.2499 + } else { 1.2500 + rv = CERT_AddCertToListHeadWithData(certList,newCert,nickname); 1.2501 + } 1.2502 + /* if we didn't add the cert to the list, don't leak it */ 1.2503 + if (rv != SECSuccess) { 1.2504 + CERT_DestroyCertificate(newCert); 1.2505 + } 1.2506 + } 1.2507 + nssCryptokiObjectArray_Destroy(instances); 1.2508 + } 1.2509 + return PR_SUCCESS; 1.2510 +} 1.2511 + 1.2512 + 1.2513 +CERTCertList * 1.2514 +PK11_ListCerts(PK11CertListType type, void *pwarg) 1.2515 +{ 1.2516 + NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); 1.2517 + CERTCertList *certList = NULL; 1.2518 + struct listCertsStr listCerts; 1.2519 + certList = CERT_NewCertList(); 1.2520 + listCerts.type = type; 1.2521 + listCerts.certList = certList; 1.2522 + 1.2523 + /* authenticate to the slots */ 1.2524 + (void) pk11_TraverseAllSlots( NULL, NULL, PR_TRUE, pwarg); 1.2525 + NSSTrustDomain_TraverseCertificates(defaultTD, pk11ListCertCallback, 1.2526 + &listCerts); 1.2527 + return certList; 1.2528 +} 1.2529 + 1.2530 +SECItem * 1.2531 +PK11_GetLowLevelKeyIDForCert(PK11SlotInfo *slot, 1.2532 + CERTCertificate *cert, void *wincx) 1.2533 +{ 1.2534 + CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; 1.2535 + CK_ATTRIBUTE theTemplate[] = { 1.2536 + { CKA_VALUE, NULL, 0 }, 1.2537 + { CKA_CLASS, NULL, 0 } 1.2538 + }; 1.2539 + /* if you change the array, change the variable below as well */ 1.2540 + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); 1.2541 + CK_OBJECT_HANDLE certHandle; 1.2542 + CK_ATTRIBUTE *attrs = theTemplate; 1.2543 + PK11SlotInfo *slotRef = NULL; 1.2544 + SECItem *item; 1.2545 + SECStatus rv; 1.2546 + 1.2547 + if (slot) { 1.2548 + PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, 1.2549 + cert->derCert.len); attrs++; 1.2550 + PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); 1.2551 + 1.2552 + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); 1.2553 + if (rv != SECSuccess) { 1.2554 + return NULL; 1.2555 + } 1.2556 + certHandle = pk11_getcerthandle(slot,cert,theTemplate,tsize); 1.2557 + } else { 1.2558 + certHandle = PK11_FindObjectForCert(cert, wincx, &slotRef); 1.2559 + if (certHandle == CK_INVALID_HANDLE) { 1.2560 + return pk11_mkcertKeyID(cert); 1.2561 + } 1.2562 + slot = slotRef; 1.2563 + } 1.2564 + 1.2565 + if (certHandle == CK_INVALID_HANDLE) { 1.2566 + return NULL; 1.2567 + } 1.2568 + 1.2569 + item = pk11_GetLowLevelKeyFromHandle(slot,certHandle); 1.2570 + if (slotRef) PK11_FreeSlot(slotRef); 1.2571 + return item; 1.2572 +} 1.2573 + 1.2574 +/* argument type for listCertsCallback */ 1.2575 +typedef struct { 1.2576 + CERTCertList *list; 1.2577 + PK11SlotInfo *slot; 1.2578 +} ListCertsArg; 1.2579 + 1.2580 +static SECStatus 1.2581 +listCertsCallback(CERTCertificate* cert, void*arg) 1.2582 +{ 1.2583 + ListCertsArg *cdata = (ListCertsArg*)arg; 1.2584 + char *nickname = NULL; 1.2585 + nssCryptokiObject *instance, **ci; 1.2586 + nssCryptokiObject **instances; 1.2587 + NSSCertificate *c = STAN_GetNSSCertificate(cert); 1.2588 + SECStatus rv; 1.2589 + 1.2590 + if (c == NULL) { 1.2591 + return SECFailure; 1.2592 + } 1.2593 + instances = nssPKIObject_GetInstances(&c->object); 1.2594 + if (!instances) { 1.2595 + return SECFailure; 1.2596 + } 1.2597 + instance = NULL; 1.2598 + for (ci = instances; *ci; ci++) { 1.2599 + if ((*ci)->token->pk11slot == cdata->slot) { 1.2600 + instance = *ci; 1.2601 + break; 1.2602 + } 1.2603 + } 1.2604 + PORT_Assert(instance != NULL); 1.2605 + if (!instance) { 1.2606 + nssCryptokiObjectArray_Destroy(instances); 1.2607 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1.2608 + return SECFailure; 1.2609 + } 1.2610 + nickname = STAN_GetCERTCertificateNameForInstance(cdata->list->arena, 1.2611 + c, instance); 1.2612 + nssCryptokiObjectArray_Destroy(instances); 1.2613 + 1.2614 + CERT_DupCertificate(cert); 1.2615 + rv = CERT_AddCertToListTailWithData(cdata->list, cert, nickname); 1.2616 + if (rv != SECSuccess) { 1.2617 + CERT_DestroyCertificate(cert); 1.2618 + } 1.2619 + return rv; 1.2620 +} 1.2621 + 1.2622 +CERTCertList * 1.2623 +PK11_ListCertsInSlot(PK11SlotInfo *slot) 1.2624 +{ 1.2625 + SECStatus status; 1.2626 + CERTCertList *certs; 1.2627 + ListCertsArg cdata; 1.2628 + 1.2629 + certs = CERT_NewCertList(); 1.2630 + if(certs == NULL) return NULL; 1.2631 + cdata.list = certs; 1.2632 + cdata.slot = slot; 1.2633 + 1.2634 + status = PK11_TraverseCertsInSlot(slot, listCertsCallback, 1.2635 + &cdata); 1.2636 + 1.2637 + if( status != SECSuccess ) { 1.2638 + CERT_DestroyCertList(certs); 1.2639 + certs = NULL; 1.2640 + } 1.2641 + 1.2642 + return certs; 1.2643 +} 1.2644 + 1.2645 +PK11SlotList * 1.2646 +PK11_GetAllSlotsForCert(CERTCertificate *cert, void *arg) 1.2647 +{ 1.2648 + nssCryptokiObject **ip; 1.2649 + PK11SlotList *slotList; 1.2650 + NSSCertificate *c; 1.2651 + nssCryptokiObject **instances; 1.2652 + PRBool found = PR_FALSE; 1.2653 + 1.2654 + if (!cert) { 1.2655 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.2656 + return NULL; 1.2657 + } 1.2658 + 1.2659 + c = STAN_GetNSSCertificate(cert); 1.2660 + if (!c) { 1.2661 + CERT_MapStanError(); 1.2662 + return NULL; 1.2663 + } 1.2664 + 1.2665 + /* add multiple instances to the cert list */ 1.2666 + instances = nssPKIObject_GetInstances(&c->object); 1.2667 + if (!instances) { 1.2668 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.2669 + return NULL; 1.2670 + } 1.2671 + 1.2672 + slotList = PK11_NewSlotList(); 1.2673 + if (!slotList) { 1.2674 + nssCryptokiObjectArray_Destroy(instances); 1.2675 + return NULL; 1.2676 + } 1.2677 + 1.2678 + for (ip = instances; *ip; ip++) { 1.2679 + nssCryptokiObject *instance = *ip; 1.2680 + PK11SlotInfo *slot = instance->token->pk11slot; 1.2681 + if (slot) { 1.2682 + PK11_AddSlotToList(slotList, slot, PR_TRUE); 1.2683 + found = PR_TRUE; 1.2684 + } 1.2685 + } 1.2686 + if (!found) { 1.2687 + PK11_FreeSlotList(slotList); 1.2688 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.2689 + slotList = NULL; 1.2690 + } 1.2691 + 1.2692 + nssCryptokiObjectArray_Destroy(instances); 1.2693 + return slotList; 1.2694 +}