1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/dev/devtoken.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1580 @@ 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 +#include "pkcs11.h" 1.9 + 1.10 +#ifndef DEVM_H 1.11 +#include "devm.h" 1.12 +#endif /* DEVM_H */ 1.13 + 1.14 +#ifndef CKHELPER_H 1.15 +#include "ckhelper.h" 1.16 +#endif /* CKHELPER_H */ 1.17 + 1.18 +#include "pk11func.h" 1.19 +#include "dev3hack.h" 1.20 +#include "secerr.h" 1.21 + 1.22 +extern const NSSError NSS_ERROR_NOT_FOUND; 1.23 +extern const NSSError NSS_ERROR_INVALID_ARGUMENT; 1.24 +extern const NSSError NSS_ERROR_PKCS11; 1.25 + 1.26 +/* The number of object handles to grab during each call to C_FindObjects */ 1.27 +#define OBJECT_STACK_SIZE 16 1.28 + 1.29 +NSS_IMPLEMENT PRStatus 1.30 +nssToken_Destroy ( 1.31 + NSSToken *tok 1.32 +) 1.33 +{ 1.34 + if (tok) { 1.35 + if (PR_ATOMIC_DECREMENT(&tok->base.refCount) == 0) { 1.36 + PZ_DestroyLock(tok->base.lock); 1.37 + nssTokenObjectCache_Destroy(tok->cache); 1.38 + /* The token holds the first/last reference to the slot. 1.39 + * When the token is actually destroyed, that ref must go too. 1.40 + */ 1.41 + (void)nssSlot_Destroy(tok->slot); 1.42 + return nssArena_Destroy(tok->base.arena); 1.43 + } 1.44 + } 1.45 + return PR_SUCCESS; 1.46 +} 1.47 + 1.48 +NSS_IMPLEMENT void 1.49 +nssToken_Remove ( 1.50 + NSSToken *tok 1.51 +) 1.52 +{ 1.53 + nssTokenObjectCache_Clear(tok->cache); 1.54 +} 1.55 + 1.56 +NSS_IMPLEMENT void 1.57 +NSSToken_Destroy ( 1.58 + NSSToken *tok 1.59 +) 1.60 +{ 1.61 + (void)nssToken_Destroy(tok); 1.62 +} 1.63 + 1.64 +NSS_IMPLEMENT NSSToken * 1.65 +nssToken_AddRef ( 1.66 + NSSToken *tok 1.67 +) 1.68 +{ 1.69 + PR_ATOMIC_INCREMENT(&tok->base.refCount); 1.70 + return tok; 1.71 +} 1.72 + 1.73 +NSS_IMPLEMENT NSSSlot * 1.74 +nssToken_GetSlot ( 1.75 + NSSToken *tok 1.76 +) 1.77 +{ 1.78 + return nssSlot_AddRef(tok->slot); 1.79 +} 1.80 + 1.81 +NSS_IMPLEMENT void * 1.82 +nssToken_GetCryptokiEPV ( 1.83 + NSSToken *token 1.84 +) 1.85 +{ 1.86 + return nssSlot_GetCryptokiEPV(token->slot); 1.87 +} 1.88 + 1.89 +NSS_IMPLEMENT nssSession * 1.90 +nssToken_GetDefaultSession ( 1.91 + NSSToken *token 1.92 +) 1.93 +{ 1.94 + return token->defaultSession; 1.95 +} 1.96 + 1.97 +NSS_IMPLEMENT NSSUTF8 * 1.98 +nssToken_GetName ( 1.99 + NSSToken *tok 1.100 +) 1.101 +{ 1.102 + if (tok == NULL) { 1.103 + return ""; 1.104 + } 1.105 + if (tok->base.name[0] == 0) { 1.106 + (void) nssSlot_IsTokenPresent(tok->slot); 1.107 + } 1.108 + return tok->base.name; 1.109 +} 1.110 + 1.111 +NSS_IMPLEMENT NSSUTF8 * 1.112 +NSSToken_GetName ( 1.113 + NSSToken *token 1.114 +) 1.115 +{ 1.116 + return nssToken_GetName(token); 1.117 +} 1.118 + 1.119 +NSS_IMPLEMENT PRBool 1.120 +nssToken_IsLoginRequired ( 1.121 + NSSToken *token 1.122 +) 1.123 +{ 1.124 + return (token->ckFlags & CKF_LOGIN_REQUIRED); 1.125 +} 1.126 + 1.127 +NSS_IMPLEMENT PRBool 1.128 +nssToken_NeedsPINInitialization ( 1.129 + NSSToken *token 1.130 +) 1.131 +{ 1.132 + return (!(token->ckFlags & CKF_USER_PIN_INITIALIZED)); 1.133 +} 1.134 + 1.135 +NSS_IMPLEMENT PRStatus 1.136 +nssToken_DeleteStoredObject ( 1.137 + nssCryptokiObject *instance 1.138 +) 1.139 +{ 1.140 + CK_RV ckrv; 1.141 + PRStatus status; 1.142 + PRBool createdSession = PR_FALSE; 1.143 + NSSToken *token = instance->token; 1.144 + nssSession *session = NULL; 1.145 + void *epv = nssToken_GetCryptokiEPV(instance->token); 1.146 + if (token->cache) { 1.147 + nssTokenObjectCache_RemoveObject(token->cache, instance); 1.148 + } 1.149 + if (instance->isTokenObject) { 1.150 + if (token->defaultSession && 1.151 + nssSession_IsReadWrite(token->defaultSession)) { 1.152 + session = token->defaultSession; 1.153 + } else { 1.154 + session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE); 1.155 + createdSession = PR_TRUE; 1.156 + } 1.157 + } 1.158 + if (session == NULL) { 1.159 + return PR_FAILURE; 1.160 + } 1.161 + nssSession_EnterMonitor(session); 1.162 + ckrv = CKAPI(epv)->C_DestroyObject(session->handle, instance->handle); 1.163 + nssSession_ExitMonitor(session); 1.164 + if (createdSession) { 1.165 + nssSession_Destroy(session); 1.166 + } 1.167 + status = PR_SUCCESS; 1.168 + if (ckrv != CKR_OK) { 1.169 + status = PR_FAILURE; 1.170 + /* use the error stack to pass the PKCS #11 error out */ 1.171 + nss_SetError(ckrv); 1.172 + nss_SetError(NSS_ERROR_PKCS11); 1.173 + } 1.174 + return status; 1.175 +} 1.176 + 1.177 +static nssCryptokiObject * 1.178 +import_object ( 1.179 + NSSToken *tok, 1.180 + nssSession *sessionOpt, 1.181 + CK_ATTRIBUTE_PTR objectTemplate, 1.182 + CK_ULONG otsize 1.183 +) 1.184 +{ 1.185 + nssSession *session = NULL; 1.186 + PRBool createdSession = PR_FALSE; 1.187 + nssCryptokiObject *object = NULL; 1.188 + CK_OBJECT_HANDLE handle; 1.189 + CK_RV ckrv; 1.190 + void *epv = nssToken_GetCryptokiEPV(tok); 1.191 + if (nssCKObject_IsTokenObjectTemplate(objectTemplate, otsize)) { 1.192 + if (sessionOpt) { 1.193 + if (!nssSession_IsReadWrite(sessionOpt)) { 1.194 + nss_SetError(NSS_ERROR_INVALID_ARGUMENT); 1.195 + return NULL; 1.196 + } 1.197 + session = sessionOpt; 1.198 + } else if (tok->defaultSession && 1.199 + nssSession_IsReadWrite(tok->defaultSession)) { 1.200 + session = tok->defaultSession; 1.201 + } else { 1.202 + session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE); 1.203 + createdSession = PR_TRUE; 1.204 + } 1.205 + } else { 1.206 + session = (sessionOpt) ? sessionOpt : tok->defaultSession; 1.207 + } 1.208 + if (session == NULL) { 1.209 + nss_SetError(NSS_ERROR_INVALID_ARGUMENT); 1.210 + return NULL; 1.211 + } 1.212 + nssSession_EnterMonitor(session); 1.213 + ckrv = CKAPI(epv)->C_CreateObject(session->handle, 1.214 + objectTemplate, otsize, 1.215 + &handle); 1.216 + nssSession_ExitMonitor(session); 1.217 + if (ckrv == CKR_OK) { 1.218 + object = nssCryptokiObject_Create(tok, session, handle); 1.219 + } else { 1.220 + nss_SetError(ckrv); 1.221 + nss_SetError(NSS_ERROR_PKCS11); 1.222 + } 1.223 + if (createdSession) { 1.224 + nssSession_Destroy(session); 1.225 + } 1.226 + return object; 1.227 +} 1.228 + 1.229 +static nssCryptokiObject ** 1.230 +create_objects_from_handles ( 1.231 + NSSToken *tok, 1.232 + nssSession *session, 1.233 + CK_OBJECT_HANDLE *handles, 1.234 + PRUint32 numH 1.235 +) 1.236 +{ 1.237 + nssCryptokiObject **objects; 1.238 + objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numH + 1); 1.239 + if (objects) { 1.240 + PRInt32 i; 1.241 + for (i=0; i<(PRInt32)numH; i++) { 1.242 + objects[i] = nssCryptokiObject_Create(tok, session, handles[i]); 1.243 + if (!objects[i]) { 1.244 + for (--i; i>0; --i) { 1.245 + nssCryptokiObject_Destroy(objects[i]); 1.246 + } 1.247 + nss_ZFreeIf(objects); 1.248 + objects = NULL; 1.249 + break; 1.250 + } 1.251 + } 1.252 + } 1.253 + return objects; 1.254 +} 1.255 + 1.256 +static nssCryptokiObject ** 1.257 +find_objects ( 1.258 + NSSToken *tok, 1.259 + nssSession *sessionOpt, 1.260 + CK_ATTRIBUTE_PTR obj_template, 1.261 + CK_ULONG otsize, 1.262 + PRUint32 maximumOpt, 1.263 + PRStatus *statusOpt 1.264 +) 1.265 +{ 1.266 + CK_RV ckrv = CKR_OK; 1.267 + CK_ULONG count; 1.268 + CK_OBJECT_HANDLE *objectHandles = NULL; 1.269 + CK_OBJECT_HANDLE staticObjects[OBJECT_STACK_SIZE]; 1.270 + PRUint32 arraySize, numHandles; 1.271 + void *epv = nssToken_GetCryptokiEPV(tok); 1.272 + nssCryptokiObject **objects; 1.273 + nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; 1.274 + 1.275 + /* Don't ask the module to use an invalid session handle. */ 1.276 + if (!session || session->handle == CK_INVALID_SESSION) { 1.277 + ckrv = CKR_SESSION_HANDLE_INVALID; 1.278 + goto loser; 1.279 + } 1.280 + 1.281 + /* the arena is only for the array of object handles */ 1.282 + if (maximumOpt > 0) { 1.283 + arraySize = maximumOpt; 1.284 + } else { 1.285 + arraySize = OBJECT_STACK_SIZE; 1.286 + } 1.287 + numHandles = 0; 1.288 + if (arraySize <= OBJECT_STACK_SIZE) { 1.289 + objectHandles = staticObjects; 1.290 + } else { 1.291 + objectHandles = nss_ZNEWARRAY(NULL, CK_OBJECT_HANDLE, arraySize); 1.292 + } 1.293 + if (!objectHandles) { 1.294 + ckrv = CKR_HOST_MEMORY; 1.295 + goto loser; 1.296 + } 1.297 + nssSession_EnterMonitor(session); /* ==== session lock === */ 1.298 + /* Initialize the find with the template */ 1.299 + ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, 1.300 + obj_template, otsize); 1.301 + if (ckrv != CKR_OK) { 1.302 + nssSession_ExitMonitor(session); 1.303 + goto loser; 1.304 + } 1.305 + while (PR_TRUE) { 1.306 + /* Issue the find for up to arraySize - numHandles objects */ 1.307 + ckrv = CKAPI(epv)->C_FindObjects(session->handle, 1.308 + objectHandles + numHandles, 1.309 + arraySize - numHandles, 1.310 + &count); 1.311 + if (ckrv != CKR_OK) { 1.312 + nssSession_ExitMonitor(session); 1.313 + goto loser; 1.314 + } 1.315 + /* bump the number of found objects */ 1.316 + numHandles += count; 1.317 + if (maximumOpt > 0 || numHandles < arraySize) { 1.318 + /* When a maximum is provided, the search is done all at once, 1.319 + * so the search is finished. If the number returned was less 1.320 + * than the number sought, the search is finished. 1.321 + */ 1.322 + break; 1.323 + } 1.324 + /* the array is filled, double it and continue */ 1.325 + arraySize *= 2; 1.326 + if (objectHandles == staticObjects) { 1.327 + objectHandles = nss_ZNEWARRAY(NULL,CK_OBJECT_HANDLE, arraySize); 1.328 + if (objectHandles) { 1.329 + PORT_Memcpy(objectHandles, staticObjects, 1.330 + OBJECT_STACK_SIZE * sizeof(objectHandles[1])); 1.331 + } 1.332 + } else { 1.333 + objectHandles = nss_ZREALLOCARRAY(objectHandles, 1.334 + CK_OBJECT_HANDLE, 1.335 + arraySize); 1.336 + } 1.337 + if (!objectHandles) { 1.338 + nssSession_ExitMonitor(session); 1.339 + ckrv = CKR_HOST_MEMORY; 1.340 + goto loser; 1.341 + } 1.342 + } 1.343 + ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle); 1.344 + nssSession_ExitMonitor(session); /* ==== end session lock === */ 1.345 + if (ckrv != CKR_OK) { 1.346 + goto loser; 1.347 + } 1.348 + if (numHandles > 0) { 1.349 + objects = create_objects_from_handles(tok, session, 1.350 + objectHandles, numHandles); 1.351 + } else { 1.352 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.353 + objects = NULL; 1.354 + } 1.355 + if (objectHandles && objectHandles != staticObjects) { 1.356 + nss_ZFreeIf(objectHandles); 1.357 + } 1.358 + if (statusOpt) *statusOpt = PR_SUCCESS; 1.359 + return objects; 1.360 +loser: 1.361 + if (objectHandles && objectHandles != staticObjects) { 1.362 + nss_ZFreeIf(objectHandles); 1.363 + } 1.364 + /* 1.365 + * These errors should be treated the same as if the objects just weren't 1.366 + * found.. 1.367 + */ 1.368 + if ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) || 1.369 + (ckrv == CKR_ATTRIBUTE_VALUE_INVALID) || 1.370 + (ckrv == CKR_DATA_INVALID) || 1.371 + (ckrv == CKR_DATA_LEN_RANGE) || 1.372 + (ckrv == CKR_FUNCTION_NOT_SUPPORTED) || 1.373 + (ckrv == CKR_TEMPLATE_INCOMPLETE) || 1.374 + (ckrv == CKR_TEMPLATE_INCONSISTENT)) { 1.375 + 1.376 + nss_SetError(NSS_ERROR_NOT_FOUND); 1.377 + if (statusOpt) *statusOpt = PR_SUCCESS; 1.378 + } else { 1.379 + nss_SetError(ckrv); 1.380 + nss_SetError(NSS_ERROR_PKCS11); 1.381 + if (statusOpt) *statusOpt = PR_FAILURE; 1.382 + } 1.383 + return (nssCryptokiObject **)NULL; 1.384 +} 1.385 + 1.386 +static nssCryptokiObject ** 1.387 +find_objects_by_template ( 1.388 + NSSToken *token, 1.389 + nssSession *sessionOpt, 1.390 + CK_ATTRIBUTE_PTR obj_template, 1.391 + CK_ULONG otsize, 1.392 + PRUint32 maximumOpt, 1.393 + PRStatus *statusOpt 1.394 +) 1.395 +{ 1.396 + CK_OBJECT_CLASS objclass = (CK_OBJECT_CLASS)-1; 1.397 + nssCryptokiObject **objects = NULL; 1.398 + PRUint32 i; 1.399 + 1.400 + if (!token) { 1.401 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.402 + if (statusOpt) 1.403 + *statusOpt = PR_FAILURE; 1.404 + return NULL; 1.405 + } 1.406 + for (i=0; i<otsize; i++) { 1.407 + if (obj_template[i].type == CKA_CLASS) { 1.408 + objclass = *(CK_OBJECT_CLASS *)obj_template[i].pValue; 1.409 + break; 1.410 + } 1.411 + } 1.412 + PR_ASSERT(i < otsize); 1.413 + if (i == otsize) { 1.414 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1.415 + if (statusOpt) *statusOpt = PR_FAILURE; 1.416 + return NULL; 1.417 + } 1.418 + /* If these objects are being cached, try looking there first */ 1.419 + if (token->cache && 1.420 + nssTokenObjectCache_HaveObjectClass(token->cache, objclass)) 1.421 + { 1.422 + PRStatus status; 1.423 + objects = nssTokenObjectCache_FindObjectsByTemplate(token->cache, 1.424 + objclass, 1.425 + obj_template, 1.426 + otsize, 1.427 + maximumOpt, 1.428 + &status); 1.429 + if (status == PR_SUCCESS) { 1.430 + if (statusOpt) *statusOpt = status; 1.431 + return objects; 1.432 + } 1.433 + } 1.434 + /* Either they are not cached, or cache failed; look on token. */ 1.435 + objects = find_objects(token, sessionOpt, 1.436 + obj_template, otsize, 1.437 + maximumOpt, statusOpt); 1.438 + return objects; 1.439 +} 1.440 + 1.441 +extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; 1.442 + 1.443 +NSS_IMPLEMENT nssCryptokiObject * 1.444 +nssToken_ImportCertificate ( 1.445 + NSSToken *tok, 1.446 + nssSession *sessionOpt, 1.447 + NSSCertificateType certType, 1.448 + NSSItem *id, 1.449 + const NSSUTF8 *nickname, 1.450 + NSSDER *encoding, 1.451 + NSSDER *issuer, 1.452 + NSSDER *subject, 1.453 + NSSDER *serial, 1.454 + NSSASCII7 *email, 1.455 + PRBool asTokenObject 1.456 +) 1.457 +{ 1.458 + PRStatus status; 1.459 + CK_CERTIFICATE_TYPE cert_type; 1.460 + CK_ATTRIBUTE_PTR attr; 1.461 + CK_ATTRIBUTE cert_tmpl[10]; 1.462 + CK_ULONG ctsize; 1.463 + nssTokenSearchType searchType; 1.464 + nssCryptokiObject *rvObject = NULL; 1.465 + 1.466 + if (!tok) { 1.467 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.468 + return NULL; 1.469 + } 1.470 + if (certType == NSSCertificateType_PKIX) { 1.471 + cert_type = CKC_X_509; 1.472 + } else { 1.473 + return (nssCryptokiObject *)NULL; 1.474 + } 1.475 + NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); 1.476 + if (asTokenObject) { 1.477 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.478 + searchType = nssTokenSearchType_TokenOnly; 1.479 + } else { 1.480 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.481 + searchType = nssTokenSearchType_SessionOnly; 1.482 + } 1.483 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); 1.484 + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CERTIFICATE_TYPE, cert_type); 1.485 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); 1.486 + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); 1.487 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding); 1.488 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer); 1.489 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); 1.490 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial); 1.491 + if (email) { 1.492 + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_EMAIL, email); 1.493 + } 1.494 + NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); 1.495 + /* see if the cert is already there */ 1.496 + rvObject = nssToken_FindCertificateByIssuerAndSerialNumber(tok, 1.497 + sessionOpt, 1.498 + issuer, 1.499 + serial, 1.500 + searchType, 1.501 + NULL); 1.502 + if (rvObject) { 1.503 + NSSItem existingDER; 1.504 + NSSSlot *slot = nssToken_GetSlot(tok); 1.505 + nssSession *session = nssSlot_CreateSession(slot, NULL, PR_TRUE); 1.506 + if (!session) { 1.507 + nssCryptokiObject_Destroy(rvObject); 1.508 + nssSlot_Destroy(slot); 1.509 + return (nssCryptokiObject *)NULL; 1.510 + } 1.511 + /* Reject any attempt to import a new cert that has the same 1.512 + * issuer/serial as an existing cert, but does not have the 1.513 + * same encoding 1.514 + */ 1.515 + NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); 1.516 + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE); 1.517 + NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); 1.518 + status = nssCKObject_GetAttributes(rvObject->handle, 1.519 + cert_tmpl, ctsize, NULL, 1.520 + session, slot); 1.521 + NSS_CK_ATTRIBUTE_TO_ITEM(cert_tmpl, &existingDER); 1.522 + if (status == PR_SUCCESS) { 1.523 + if (!nssItem_Equal(encoding, &existingDER, NULL)) { 1.524 + nss_SetError(NSS_ERROR_INVALID_CERTIFICATE); 1.525 + status = PR_FAILURE; 1.526 + } 1.527 + nss_ZFreeIf(existingDER.data); 1.528 + } 1.529 + if (status == PR_FAILURE) { 1.530 + nssCryptokiObject_Destroy(rvObject); 1.531 + nssSession_Destroy(session); 1.532 + nssSlot_Destroy(slot); 1.533 + return (nssCryptokiObject *)NULL; 1.534 + } 1.535 + /* according to PKCS#11, label, ID, issuer, and serial number 1.536 + * may change after the object has been created. For PKIX, the 1.537 + * last two attributes can't change, so for now we'll only worry 1.538 + * about the first two. 1.539 + */ 1.540 + NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); 1.541 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); 1.542 + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); 1.543 + NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); 1.544 + /* reset the mutable attributes on the token */ 1.545 + nssCKObject_SetAttributes(rvObject->handle, 1.546 + cert_tmpl, ctsize, 1.547 + session, slot); 1.548 + if (!rvObject->label && nickname) { 1.549 + rvObject->label = nssUTF8_Duplicate(nickname, NULL); 1.550 + } 1.551 + nssSession_Destroy(session); 1.552 + nssSlot_Destroy(slot); 1.553 + } else { 1.554 + /* Import the certificate onto the token */ 1.555 + rvObject = import_object(tok, sessionOpt, cert_tmpl, ctsize); 1.556 + } 1.557 + if (rvObject && tok->cache) { 1.558 + /* The cache will overwrite the attributes if the object already 1.559 + * exists. 1.560 + */ 1.561 + nssTokenObjectCache_ImportObject(tok->cache, rvObject, 1.562 + CKO_CERTIFICATE, 1.563 + cert_tmpl, ctsize); 1.564 + } 1.565 + return rvObject; 1.566 +} 1.567 + 1.568 +/* traverse all objects of the given class - this should only happen 1.569 + * if the token has been marked as "traversable" 1.570 + */ 1.571 +NSS_IMPLEMENT nssCryptokiObject ** 1.572 +nssToken_FindObjects ( 1.573 + NSSToken *token, 1.574 + nssSession *sessionOpt, 1.575 + CK_OBJECT_CLASS objclass, 1.576 + nssTokenSearchType searchType, 1.577 + PRUint32 maximumOpt, 1.578 + PRStatus *statusOpt 1.579 +) 1.580 +{ 1.581 + CK_ATTRIBUTE_PTR attr; 1.582 + CK_ATTRIBUTE obj_template[2]; 1.583 + CK_ULONG obj_size; 1.584 + nssCryptokiObject **objects; 1.585 + NSS_CK_TEMPLATE_START(obj_template, attr, obj_size); 1.586 + /* Set the search to token/session only if provided */ 1.587 + if (searchType == nssTokenSearchType_SessionOnly) { 1.588 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.589 + } else if (searchType == nssTokenSearchType_TokenOnly || 1.590 + searchType == nssTokenSearchType_TokenForced) { 1.591 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.592 + } 1.593 + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, objclass); 1.594 + NSS_CK_TEMPLATE_FINISH(obj_template, attr, obj_size); 1.595 + 1.596 + if (searchType == nssTokenSearchType_TokenForced) { 1.597 + objects = find_objects(token, sessionOpt, 1.598 + obj_template, obj_size, 1.599 + maximumOpt, statusOpt); 1.600 + } else { 1.601 + objects = find_objects_by_template(token, sessionOpt, 1.602 + obj_template, obj_size, 1.603 + maximumOpt, statusOpt); 1.604 + } 1.605 + return objects; 1.606 +} 1.607 + 1.608 +NSS_IMPLEMENT nssCryptokiObject ** 1.609 +nssToken_FindCertificatesBySubject ( 1.610 + NSSToken *token, 1.611 + nssSession *sessionOpt, 1.612 + NSSDER *subject, 1.613 + nssTokenSearchType searchType, 1.614 + PRUint32 maximumOpt, 1.615 + PRStatus *statusOpt 1.616 +) 1.617 +{ 1.618 + CK_ATTRIBUTE_PTR attr; 1.619 + CK_ATTRIBUTE subj_template[3]; 1.620 + CK_ULONG stsize; 1.621 + nssCryptokiObject **objects; 1.622 + NSS_CK_TEMPLATE_START(subj_template, attr, stsize); 1.623 + /* Set the search to token/session only if provided */ 1.624 + if (searchType == nssTokenSearchType_SessionOnly) { 1.625 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.626 + } else if (searchType == nssTokenSearchType_TokenOnly) { 1.627 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.628 + } 1.629 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); 1.630 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); 1.631 + NSS_CK_TEMPLATE_FINISH(subj_template, attr, stsize); 1.632 + /* now locate the token certs matching this template */ 1.633 + objects = find_objects_by_template(token, sessionOpt, 1.634 + subj_template, stsize, 1.635 + maximumOpt, statusOpt); 1.636 + return objects; 1.637 +} 1.638 + 1.639 +NSS_IMPLEMENT nssCryptokiObject ** 1.640 +nssToken_FindCertificatesByNickname ( 1.641 + NSSToken *token, 1.642 + nssSession *sessionOpt, 1.643 + const NSSUTF8 *name, 1.644 + nssTokenSearchType searchType, 1.645 + PRUint32 maximumOpt, 1.646 + PRStatus *statusOpt 1.647 +) 1.648 +{ 1.649 + CK_ATTRIBUTE_PTR attr; 1.650 + CK_ATTRIBUTE nick_template[3]; 1.651 + CK_ULONG ntsize; 1.652 + nssCryptokiObject **objects; 1.653 + NSS_CK_TEMPLATE_START(nick_template, attr, ntsize); 1.654 + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, name); 1.655 + /* Set the search to token/session only if provided */ 1.656 + if (searchType == nssTokenSearchType_SessionOnly) { 1.657 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.658 + } else if (searchType == nssTokenSearchType_TokenOnly) { 1.659 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.660 + } 1.661 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); 1.662 + NSS_CK_TEMPLATE_FINISH(nick_template, attr, ntsize); 1.663 + /* now locate the token certs matching this template */ 1.664 + objects = find_objects_by_template(token, sessionOpt, 1.665 + nick_template, ntsize, 1.666 + maximumOpt, statusOpt); 1.667 + if (!objects) { 1.668 + /* This is to workaround the fact that PKCS#11 doesn't specify 1.669 + * whether the '\0' should be included. XXX Is that still true? 1.670 + * im - this is not needed by the current softoken. However, I'm 1.671 + * leaving it in until I have surveyed more tokens to see if it needed. 1.672 + * well, its needed by the builtin token... 1.673 + */ 1.674 + nick_template[0].ulValueLen++; 1.675 + objects = find_objects_by_template(token, sessionOpt, 1.676 + nick_template, ntsize, 1.677 + maximumOpt, statusOpt); 1.678 + } 1.679 + return objects; 1.680 +} 1.681 + 1.682 +/* XXX 1.683 + * This function *does not* use the token object cache, because not even 1.684 + * the softoken will return a value for CKA_NSS_EMAIL from a call 1.685 + * to GetAttributes. The softoken does allow searches with that attribute, 1.686 + * it just won't return a value for it. 1.687 + */ 1.688 +NSS_IMPLEMENT nssCryptokiObject ** 1.689 +nssToken_FindCertificatesByEmail ( 1.690 + NSSToken *token, 1.691 + nssSession *sessionOpt, 1.692 + NSSASCII7 *email, 1.693 + nssTokenSearchType searchType, 1.694 + PRUint32 maximumOpt, 1.695 + PRStatus *statusOpt 1.696 +) 1.697 +{ 1.698 + CK_ATTRIBUTE_PTR attr; 1.699 + CK_ATTRIBUTE email_template[3]; 1.700 + CK_ULONG etsize; 1.701 + nssCryptokiObject **objects; 1.702 + NSS_CK_TEMPLATE_START(email_template, attr, etsize); 1.703 + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_EMAIL, email); 1.704 + /* Set the search to token/session only if provided */ 1.705 + if (searchType == nssTokenSearchType_SessionOnly) { 1.706 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.707 + } else if (searchType == nssTokenSearchType_TokenOnly) { 1.708 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.709 + } 1.710 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); 1.711 + NSS_CK_TEMPLATE_FINISH(email_template, attr, etsize); 1.712 + /* now locate the token certs matching this template */ 1.713 + objects = find_objects(token, sessionOpt, 1.714 + email_template, etsize, 1.715 + maximumOpt, statusOpt); 1.716 + if (!objects) { 1.717 + /* This is to workaround the fact that PKCS#11 doesn't specify 1.718 + * whether the '\0' should be included. XXX Is that still true? 1.719 + * im - this is not needed by the current softoken. However, I'm 1.720 + * leaving it in until I have surveyed more tokens to see if it needed. 1.721 + * well, its needed by the builtin token... 1.722 + */ 1.723 + email_template[0].ulValueLen++; 1.724 + objects = find_objects(token, sessionOpt, 1.725 + email_template, etsize, 1.726 + maximumOpt, statusOpt); 1.727 + } 1.728 + return objects; 1.729 +} 1.730 + 1.731 +NSS_IMPLEMENT nssCryptokiObject ** 1.732 +nssToken_FindCertificatesByID ( 1.733 + NSSToken *token, 1.734 + nssSession *sessionOpt, 1.735 + NSSItem *id, 1.736 + nssTokenSearchType searchType, 1.737 + PRUint32 maximumOpt, 1.738 + PRStatus *statusOpt 1.739 +) 1.740 +{ 1.741 + CK_ATTRIBUTE_PTR attr; 1.742 + CK_ATTRIBUTE id_template[3]; 1.743 + CK_ULONG idtsize; 1.744 + nssCryptokiObject **objects; 1.745 + NSS_CK_TEMPLATE_START(id_template, attr, idtsize); 1.746 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); 1.747 + /* Set the search to token/session only if provided */ 1.748 + if (searchType == nssTokenSearchType_SessionOnly) { 1.749 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.750 + } else if (searchType == nssTokenSearchType_TokenOnly) { 1.751 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.752 + } 1.753 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); 1.754 + NSS_CK_TEMPLATE_FINISH(id_template, attr, idtsize); 1.755 + /* now locate the token certs matching this template */ 1.756 + objects = find_objects_by_template(token, sessionOpt, 1.757 + id_template, idtsize, 1.758 + maximumOpt, statusOpt); 1.759 + return objects; 1.760 +} 1.761 + 1.762 +/* 1.763 + * decode the serial item and return our result. 1.764 + * NOTE serialDecode's data is really stored in serial. Don't free it. 1.765 + */ 1.766 +static PRStatus 1.767 +nssToken_decodeSerialItem(NSSItem *serial, NSSItem *serialDecode) 1.768 +{ 1.769 + unsigned char *data = (unsigned char *)serial->data; 1.770 + int data_left, data_len, index; 1.771 + 1.772 + if ((serial->size >= 3) && (data[0] == 0x2)) { 1.773 + /* remove the der encoding of the serial number before generating the 1.774 + * key.. */ 1.775 + data_left = serial->size-2; 1.776 + data_len = data[1]; 1.777 + index = 2; 1.778 + 1.779 + /* extended length ? (not very likely for a serial number) */ 1.780 + if (data_len & 0x80) { 1.781 + int len_count = data_len & 0x7f; 1.782 + 1.783 + data_len = 0; 1.784 + data_left -= len_count; 1.785 + if (data_left > 0) { 1.786 + while (len_count --) { 1.787 + data_len = (data_len << 8) | data[index++]; 1.788 + } 1.789 + } 1.790 + } 1.791 + /* XXX leaving any leading zeros on the serial number for backwards 1.792 + * compatibility 1.793 + */ 1.794 + /* not a valid der, must be just an unlucky serial number value */ 1.795 + if (data_len == data_left) { 1.796 + serialDecode->size = data_len; 1.797 + serialDecode->data = &data[index]; 1.798 + return PR_SUCCESS; 1.799 + } 1.800 + } 1.801 + return PR_FAILURE; 1.802 +} 1.803 + 1.804 +NSS_IMPLEMENT nssCryptokiObject * 1.805 +nssToken_FindCertificateByIssuerAndSerialNumber ( 1.806 + NSSToken *token, 1.807 + nssSession *sessionOpt, 1.808 + NSSDER *issuer, 1.809 + NSSDER *serial, 1.810 + nssTokenSearchType searchType, 1.811 + PRStatus *statusOpt 1.812 +) 1.813 +{ 1.814 + CK_ATTRIBUTE_PTR attr; 1.815 + CK_ATTRIBUTE_PTR serialAttr; 1.816 + CK_ATTRIBUTE cert_template[4]; 1.817 + CK_ULONG ctsize; 1.818 + nssCryptokiObject **objects; 1.819 + nssCryptokiObject *rvObject = NULL; 1.820 + NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); 1.821 + 1.822 + if (!token) { 1.823 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.824 + if (statusOpt) 1.825 + *statusOpt = PR_FAILURE; 1.826 + return NULL; 1.827 + } 1.828 + /* Set the search to token/session only if provided */ 1.829 + if (searchType == nssTokenSearchType_SessionOnly) { 1.830 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.831 + } else if ((searchType == nssTokenSearchType_TokenOnly) || 1.832 + (searchType == nssTokenSearchType_TokenForced)) { 1.833 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.834 + } 1.835 + /* Set the unique id */ 1.836 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); 1.837 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer); 1.838 + serialAttr = attr; 1.839 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial); 1.840 + NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); 1.841 + /* get the object handle */ 1.842 + if (searchType == nssTokenSearchType_TokenForced) { 1.843 + objects = find_objects(token, sessionOpt, 1.844 + cert_template, ctsize, 1.845 + 1, statusOpt); 1.846 + } else { 1.847 + objects = find_objects_by_template(token, sessionOpt, 1.848 + cert_template, ctsize, 1.849 + 1, statusOpt); 1.850 + } 1.851 + if (objects) { 1.852 + rvObject = objects[0]; 1.853 + nss_ZFreeIf(objects); 1.854 + } 1.855 + 1.856 + /* 1.857 + * NSS used to incorrectly store serial numbers in their decoded form. 1.858 + * because of this old tokens have decoded serial numbers. 1.859 + */ 1.860 + if (!objects) { 1.861 + NSSItem serialDecode; 1.862 + PRStatus status; 1.863 + 1.864 + status = nssToken_decodeSerialItem(serial, &serialDecode); 1.865 + if (status != PR_SUCCESS) { 1.866 + return NULL; 1.867 + } 1.868 + NSS_CK_SET_ATTRIBUTE_ITEM(serialAttr,CKA_SERIAL_NUMBER,&serialDecode); 1.869 + if (searchType == nssTokenSearchType_TokenForced) { 1.870 + objects = find_objects(token, sessionOpt, 1.871 + cert_template, ctsize, 1.872 + 1, statusOpt); 1.873 + } else { 1.874 + objects = find_objects_by_template(token, sessionOpt, 1.875 + cert_template, ctsize, 1.876 + 1, statusOpt); 1.877 + } 1.878 + if (objects) { 1.879 + rvObject = objects[0]; 1.880 + nss_ZFreeIf(objects); 1.881 + } 1.882 + } 1.883 + return rvObject; 1.884 +} 1.885 + 1.886 +NSS_IMPLEMENT nssCryptokiObject * 1.887 +nssToken_FindCertificateByEncodedCertificate ( 1.888 + NSSToken *token, 1.889 + nssSession *sessionOpt, 1.890 + NSSBER *encodedCertificate, 1.891 + nssTokenSearchType searchType, 1.892 + PRStatus *statusOpt 1.893 +) 1.894 +{ 1.895 + CK_ATTRIBUTE_PTR attr; 1.896 + CK_ATTRIBUTE cert_template[3]; 1.897 + CK_ULONG ctsize; 1.898 + nssCryptokiObject **objects; 1.899 + nssCryptokiObject *rvObject = NULL; 1.900 + NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); 1.901 + /* Set the search to token/session only if provided */ 1.902 + if (searchType == nssTokenSearchType_SessionOnly) { 1.903 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.904 + } else if (searchType == nssTokenSearchType_TokenOnly) { 1.905 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.906 + } 1.907 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); 1.908 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encodedCertificate); 1.909 + NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); 1.910 + /* get the object handle */ 1.911 + objects = find_objects_by_template(token, sessionOpt, 1.912 + cert_template, ctsize, 1.913 + 1, statusOpt); 1.914 + if (objects) { 1.915 + rvObject = objects[0]; 1.916 + nss_ZFreeIf(objects); 1.917 + } 1.918 + return rvObject; 1.919 +} 1.920 + 1.921 +NSS_IMPLEMENT nssCryptokiObject ** 1.922 +nssToken_FindPrivateKeys ( 1.923 + NSSToken *token, 1.924 + nssSession *sessionOpt, 1.925 + nssTokenSearchType searchType, 1.926 + PRUint32 maximumOpt, 1.927 + PRStatus *statusOpt 1.928 +) 1.929 +{ 1.930 + CK_ATTRIBUTE_PTR attr; 1.931 + CK_ATTRIBUTE key_template[2]; 1.932 + CK_ULONG ktsize; 1.933 + nssCryptokiObject **objects; 1.934 + 1.935 + NSS_CK_TEMPLATE_START(key_template, attr, ktsize); 1.936 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey); 1.937 + if (searchType == nssTokenSearchType_SessionOnly) { 1.938 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.939 + } else if (searchType == nssTokenSearchType_TokenOnly) { 1.940 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.941 + } 1.942 + NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); 1.943 + 1.944 + objects = find_objects_by_template(token, sessionOpt, 1.945 + key_template, ktsize, 1.946 + maximumOpt, statusOpt); 1.947 + return objects; 1.948 +} 1.949 + 1.950 +/* XXX ?there are no session cert objects, so only search token objects */ 1.951 +NSS_IMPLEMENT nssCryptokiObject * 1.952 +nssToken_FindPrivateKeyByID ( 1.953 + NSSToken *token, 1.954 + nssSession *sessionOpt, 1.955 + NSSItem *keyID 1.956 +) 1.957 +{ 1.958 + CK_ATTRIBUTE_PTR attr; 1.959 + CK_ATTRIBUTE key_template[3]; 1.960 + CK_ULONG ktsize; 1.961 + nssCryptokiObject **objects; 1.962 + nssCryptokiObject *rvKey = NULL; 1.963 + 1.964 + NSS_CK_TEMPLATE_START(key_template, attr, ktsize); 1.965 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey); 1.966 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.967 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID); 1.968 + NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); 1.969 + 1.970 + objects = find_objects_by_template(token, sessionOpt, 1.971 + key_template, ktsize, 1.972 + 1, NULL); 1.973 + if (objects) { 1.974 + rvKey = objects[0]; 1.975 + nss_ZFreeIf(objects); 1.976 + } 1.977 + return rvKey; 1.978 +} 1.979 + 1.980 +/* XXX ?there are no session cert objects, so only search token objects */ 1.981 +NSS_IMPLEMENT nssCryptokiObject * 1.982 +nssToken_FindPublicKeyByID ( 1.983 + NSSToken *token, 1.984 + nssSession *sessionOpt, 1.985 + NSSItem *keyID 1.986 +) 1.987 +{ 1.988 + CK_ATTRIBUTE_PTR attr; 1.989 + CK_ATTRIBUTE key_template[3]; 1.990 + CK_ULONG ktsize; 1.991 + nssCryptokiObject **objects; 1.992 + nssCryptokiObject *rvKey = NULL; 1.993 + 1.994 + NSS_CK_TEMPLATE_START(key_template, attr, ktsize); 1.995 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_pubkey); 1.996 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.997 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID); 1.998 + NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); 1.999 + 1.1000 + objects = find_objects_by_template(token, sessionOpt, 1.1001 + key_template, ktsize, 1.1002 + 1, NULL); 1.1003 + if (objects) { 1.1004 + rvKey = objects[0]; 1.1005 + nss_ZFreeIf(objects); 1.1006 + } 1.1007 + return rvKey; 1.1008 +} 1.1009 + 1.1010 +static void 1.1011 +sha1_hash(NSSItem *input, NSSItem *output) 1.1012 +{ 1.1013 + NSSAlgorithmAndParameters *ap; 1.1014 + PK11SlotInfo *internal = PK11_GetInternalSlot(); 1.1015 + NSSToken *token = PK11Slot_GetNSSToken(internal); 1.1016 + ap = NSSAlgorithmAndParameters_CreateSHA1Digest(NULL); 1.1017 + (void)nssToken_Digest(token, NULL, ap, input, output, NULL); 1.1018 + PK11_FreeSlot(token->pk11slot); 1.1019 + nss_ZFreeIf(ap); 1.1020 +} 1.1021 + 1.1022 +static void 1.1023 +md5_hash(NSSItem *input, NSSItem *output) 1.1024 +{ 1.1025 + NSSAlgorithmAndParameters *ap; 1.1026 + PK11SlotInfo *internal = PK11_GetInternalSlot(); 1.1027 + NSSToken *token = PK11Slot_GetNSSToken(internal); 1.1028 + ap = NSSAlgorithmAndParameters_CreateMD5Digest(NULL); 1.1029 + (void)nssToken_Digest(token, NULL, ap, input, output, NULL); 1.1030 + PK11_FreeSlot(token->pk11slot); 1.1031 + nss_ZFreeIf(ap); 1.1032 +} 1.1033 + 1.1034 +static CK_TRUST 1.1035 +get_ck_trust ( 1.1036 + nssTrustLevel nssTrust 1.1037 +) 1.1038 +{ 1.1039 + CK_TRUST t; 1.1040 + switch (nssTrust) { 1.1041 + case nssTrustLevel_NotTrusted: t = CKT_NSS_NOT_TRUSTED; break; 1.1042 + case nssTrustLevel_TrustedDelegator: t = CKT_NSS_TRUSTED_DELEGATOR; 1.1043 + break; 1.1044 + case nssTrustLevel_ValidDelegator: t = CKT_NSS_VALID_DELEGATOR; break; 1.1045 + case nssTrustLevel_Trusted: t = CKT_NSS_TRUSTED; break; 1.1046 + case nssTrustLevel_MustVerify: t = CKT_NSS_MUST_VERIFY_TRUST; break; 1.1047 + case nssTrustLevel_Unknown: 1.1048 + default: t = CKT_NSS_TRUST_UNKNOWN; break; 1.1049 + } 1.1050 + return t; 1.1051 +} 1.1052 + 1.1053 +NSS_IMPLEMENT nssCryptokiObject * 1.1054 +nssToken_ImportTrust ( 1.1055 + NSSToken *tok, 1.1056 + nssSession *sessionOpt, 1.1057 + NSSDER *certEncoding, 1.1058 + NSSDER *certIssuer, 1.1059 + NSSDER *certSerial, 1.1060 + nssTrustLevel serverAuth, 1.1061 + nssTrustLevel clientAuth, 1.1062 + nssTrustLevel codeSigning, 1.1063 + nssTrustLevel emailProtection, 1.1064 + PRBool stepUpApproved, 1.1065 + PRBool asTokenObject 1.1066 +) 1.1067 +{ 1.1068 + nssCryptokiObject *object; 1.1069 + CK_OBJECT_CLASS tobjc = CKO_NSS_TRUST; 1.1070 + CK_TRUST ckSA, ckCA, ckCS, ckEP; 1.1071 + CK_ATTRIBUTE_PTR attr; 1.1072 + CK_ATTRIBUTE trust_tmpl[11]; 1.1073 + CK_ULONG tsize; 1.1074 + PRUint8 sha1[20]; /* this is cheating... */ 1.1075 + PRUint8 md5[16]; 1.1076 + NSSItem sha1_result, md5_result; 1.1077 + sha1_result.data = sha1; sha1_result.size = sizeof sha1; 1.1078 + md5_result.data = md5; md5_result.size = sizeof md5; 1.1079 + sha1_hash(certEncoding, &sha1_result); 1.1080 + md5_hash(certEncoding, &md5_result); 1.1081 + ckSA = get_ck_trust(serverAuth); 1.1082 + ckCA = get_ck_trust(clientAuth); 1.1083 + ckCS = get_ck_trust(codeSigning); 1.1084 + ckEP = get_ck_trust(emailProtection); 1.1085 + NSS_CK_TEMPLATE_START(trust_tmpl, attr, tsize); 1.1086 + if (asTokenObject) { 1.1087 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.1088 + } else { 1.1089 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.1090 + } 1.1091 + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); 1.1092 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer); 1.1093 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, certSerial); 1.1094 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result); 1.1095 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_MD5_HASH, &md5_result); 1.1096 + /* now set the trust values */ 1.1097 + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, ckSA); 1.1098 + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, ckCA); 1.1099 + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, ckCS); 1.1100 + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, ckEP); 1.1101 + if (stepUpApproved) { 1.1102 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TRUST_STEP_UP_APPROVED, 1.1103 + &g_ck_true); 1.1104 + } else { 1.1105 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TRUST_STEP_UP_APPROVED, 1.1106 + &g_ck_false); 1.1107 + } 1.1108 + NSS_CK_TEMPLATE_FINISH(trust_tmpl, attr, tsize); 1.1109 + /* import the trust object onto the token */ 1.1110 + object = import_object(tok, sessionOpt, trust_tmpl, tsize); 1.1111 + if (object && tok->cache) { 1.1112 + nssTokenObjectCache_ImportObject(tok->cache, object, tobjc, 1.1113 + trust_tmpl, tsize); 1.1114 + } 1.1115 + return object; 1.1116 +} 1.1117 + 1.1118 +NSS_IMPLEMENT nssCryptokiObject * 1.1119 +nssToken_FindTrustForCertificate ( 1.1120 + NSSToken *token, 1.1121 + nssSession *sessionOpt, 1.1122 + NSSDER *certEncoding, 1.1123 + NSSDER *certIssuer, 1.1124 + NSSDER *certSerial, 1.1125 + nssTokenSearchType searchType 1.1126 +) 1.1127 +{ 1.1128 + CK_OBJECT_CLASS tobjc = CKO_NSS_TRUST; 1.1129 + CK_ATTRIBUTE_PTR attr; 1.1130 + CK_ATTRIBUTE tobj_template[5]; 1.1131 + CK_ULONG tobj_size; 1.1132 + nssSession *session = sessionOpt ? sessionOpt : token->defaultSession; 1.1133 + nssCryptokiObject *object = NULL, **objects; 1.1134 + 1.1135 + /* Don't ask the module to use an invalid session handle. */ 1.1136 + if (!session || session->handle == CK_INVALID_SESSION) { 1.1137 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.1138 + return object; 1.1139 + } 1.1140 + 1.1141 + NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size); 1.1142 + if (searchType == nssTokenSearchType_TokenOnly) { 1.1143 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.1144 + } 1.1145 + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); 1.1146 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer); 1.1147 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER , certSerial); 1.1148 + NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size); 1.1149 + objects = find_objects_by_template(token, session, 1.1150 + tobj_template, tobj_size, 1.1151 + 1, NULL); 1.1152 + if (objects) { 1.1153 + object = objects[0]; 1.1154 + nss_ZFreeIf(objects); 1.1155 + } 1.1156 + return object; 1.1157 +} 1.1158 + 1.1159 +NSS_IMPLEMENT nssCryptokiObject * 1.1160 +nssToken_ImportCRL ( 1.1161 + NSSToken *token, 1.1162 + nssSession *sessionOpt, 1.1163 + NSSDER *subject, 1.1164 + NSSDER *encoding, 1.1165 + PRBool isKRL, 1.1166 + NSSUTF8 *url, 1.1167 + PRBool asTokenObject 1.1168 +) 1.1169 +{ 1.1170 + nssCryptokiObject *object; 1.1171 + CK_OBJECT_CLASS crlobjc = CKO_NSS_CRL; 1.1172 + CK_ATTRIBUTE_PTR attr; 1.1173 + CK_ATTRIBUTE crl_tmpl[6]; 1.1174 + CK_ULONG crlsize; 1.1175 + 1.1176 + NSS_CK_TEMPLATE_START(crl_tmpl, attr, crlsize); 1.1177 + if (asTokenObject) { 1.1178 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.1179 + } else { 1.1180 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.1181 + } 1.1182 + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc); 1.1183 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); 1.1184 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding); 1.1185 + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_URL, url); 1.1186 + if (isKRL) { 1.1187 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NSS_KRL, &g_ck_true); 1.1188 + } else { 1.1189 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NSS_KRL, &g_ck_false); 1.1190 + } 1.1191 + NSS_CK_TEMPLATE_FINISH(crl_tmpl, attr, crlsize); 1.1192 + 1.1193 + /* import the crl object onto the token */ 1.1194 + object = import_object(token, sessionOpt, crl_tmpl, crlsize); 1.1195 + if (object && token->cache) { 1.1196 + nssTokenObjectCache_ImportObject(token->cache, object, crlobjc, 1.1197 + crl_tmpl, crlsize); 1.1198 + } 1.1199 + return object; 1.1200 +} 1.1201 + 1.1202 +NSS_IMPLEMENT nssCryptokiObject ** 1.1203 +nssToken_FindCRLsBySubject ( 1.1204 + NSSToken *token, 1.1205 + nssSession *sessionOpt, 1.1206 + NSSDER *subject, 1.1207 + nssTokenSearchType searchType, 1.1208 + PRUint32 maximumOpt, 1.1209 + PRStatus *statusOpt 1.1210 +) 1.1211 +{ 1.1212 + CK_OBJECT_CLASS crlobjc = CKO_NSS_CRL; 1.1213 + CK_ATTRIBUTE_PTR attr; 1.1214 + CK_ATTRIBUTE crlobj_template[3]; 1.1215 + CK_ULONG crlobj_size; 1.1216 + nssCryptokiObject **objects = NULL; 1.1217 + nssSession *session = sessionOpt ? sessionOpt : token->defaultSession; 1.1218 + 1.1219 + /* Don't ask the module to use an invalid session handle. */ 1.1220 + if (!session || session->handle == CK_INVALID_SESSION) { 1.1221 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.1222 + return objects; 1.1223 + } 1.1224 + 1.1225 + NSS_CK_TEMPLATE_START(crlobj_template, attr, crlobj_size); 1.1226 + if (searchType == nssTokenSearchType_SessionOnly) { 1.1227 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.1228 + } else if (searchType == nssTokenSearchType_TokenOnly || 1.1229 + searchType == nssTokenSearchType_TokenForced) { 1.1230 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.1231 + } 1.1232 + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc); 1.1233 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); 1.1234 + NSS_CK_TEMPLATE_FINISH(crlobj_template, attr, crlobj_size); 1.1235 + 1.1236 + objects = find_objects_by_template(token, session, 1.1237 + crlobj_template, crlobj_size, 1.1238 + maximumOpt, statusOpt); 1.1239 + return objects; 1.1240 +} 1.1241 + 1.1242 +NSS_IMPLEMENT PRStatus 1.1243 +nssToken_GetCachedObjectAttributes ( 1.1244 + NSSToken *token, 1.1245 + NSSArena *arenaOpt, 1.1246 + nssCryptokiObject *object, 1.1247 + CK_OBJECT_CLASS objclass, 1.1248 + CK_ATTRIBUTE_PTR atemplate, 1.1249 + CK_ULONG atlen 1.1250 +) 1.1251 +{ 1.1252 + if (!token->cache) { 1.1253 + return PR_FAILURE; 1.1254 + } 1.1255 + return nssTokenObjectCache_GetObjectAttributes(token->cache, arenaOpt, 1.1256 + object, objclass, 1.1257 + atemplate, atlen); 1.1258 +} 1.1259 + 1.1260 +NSS_IMPLEMENT NSSItem * 1.1261 +nssToken_Digest ( 1.1262 + NSSToken *tok, 1.1263 + nssSession *sessionOpt, 1.1264 + NSSAlgorithmAndParameters *ap, 1.1265 + NSSItem *data, 1.1266 + NSSItem *rvOpt, 1.1267 + NSSArena *arenaOpt 1.1268 +) 1.1269 +{ 1.1270 + CK_RV ckrv; 1.1271 + CK_ULONG digestLen; 1.1272 + CK_BYTE_PTR digest; 1.1273 + NSSItem *rvItem = NULL; 1.1274 + void *epv = nssToken_GetCryptokiEPV(tok); 1.1275 + nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; 1.1276 + 1.1277 + /* Don't ask the module to use an invalid session handle. */ 1.1278 + if (!session || session->handle == CK_INVALID_SESSION) { 1.1279 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.1280 + return rvItem; 1.1281 + } 1.1282 + 1.1283 + nssSession_EnterMonitor(session); 1.1284 + ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism); 1.1285 + if (ckrv != CKR_OK) { 1.1286 + nssSession_ExitMonitor(session); 1.1287 + return NULL; 1.1288 + } 1.1289 +#if 0 1.1290 + /* XXX the standard says this should work, but it doesn't */ 1.1291 + ckrv = CKAPI(epv)->C_Digest(session->handle, NULL, 0, NULL, &digestLen); 1.1292 + if (ckrv != CKR_OK) { 1.1293 + nssSession_ExitMonitor(session); 1.1294 + return NULL; 1.1295 + } 1.1296 +#endif 1.1297 + digestLen = 0; /* XXX for now */ 1.1298 + digest = NULL; 1.1299 + if (rvOpt) { 1.1300 + if (rvOpt->size > 0 && rvOpt->size < digestLen) { 1.1301 + nssSession_ExitMonitor(session); 1.1302 + /* the error should be bad args */ 1.1303 + return NULL; 1.1304 + } 1.1305 + if (rvOpt->data) { 1.1306 + digest = rvOpt->data; 1.1307 + } 1.1308 + digestLen = rvOpt->size; 1.1309 + } 1.1310 + if (!digest) { 1.1311 + digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen); 1.1312 + if (!digest) { 1.1313 + nssSession_ExitMonitor(session); 1.1314 + return NULL; 1.1315 + } 1.1316 + } 1.1317 + ckrv = CKAPI(epv)->C_Digest(session->handle, 1.1318 + (CK_BYTE_PTR)data->data, 1.1319 + (CK_ULONG)data->size, 1.1320 + (CK_BYTE_PTR)digest, 1.1321 + &digestLen); 1.1322 + nssSession_ExitMonitor(session); 1.1323 + if (ckrv != CKR_OK) { 1.1324 + nss_ZFreeIf(digest); 1.1325 + return NULL; 1.1326 + } 1.1327 + if (!rvOpt) { 1.1328 + rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest); 1.1329 + } 1.1330 + return rvItem; 1.1331 +} 1.1332 + 1.1333 +NSS_IMPLEMENT PRStatus 1.1334 +nssToken_BeginDigest ( 1.1335 + NSSToken *tok, 1.1336 + nssSession *sessionOpt, 1.1337 + NSSAlgorithmAndParameters *ap 1.1338 +) 1.1339 +{ 1.1340 + CK_RV ckrv; 1.1341 + void *epv = nssToken_GetCryptokiEPV(tok); 1.1342 + nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; 1.1343 + 1.1344 + /* Don't ask the module to use an invalid session handle. */ 1.1345 + if (!session || session->handle == CK_INVALID_SESSION) { 1.1346 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.1347 + return PR_FAILURE; 1.1348 + } 1.1349 + 1.1350 + nssSession_EnterMonitor(session); 1.1351 + ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism); 1.1352 + nssSession_ExitMonitor(session); 1.1353 + return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; 1.1354 +} 1.1355 + 1.1356 +NSS_IMPLEMENT PRStatus 1.1357 +nssToken_ContinueDigest ( 1.1358 + NSSToken *tok, 1.1359 + nssSession *sessionOpt, 1.1360 + NSSItem *item 1.1361 +) 1.1362 +{ 1.1363 + CK_RV ckrv; 1.1364 + void *epv = nssToken_GetCryptokiEPV(tok); 1.1365 + nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; 1.1366 + 1.1367 + /* Don't ask the module to use an invalid session handle. */ 1.1368 + if (!session || session->handle == CK_INVALID_SESSION) { 1.1369 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.1370 + return PR_FAILURE; 1.1371 + } 1.1372 + 1.1373 + nssSession_EnterMonitor(session); 1.1374 + ckrv = CKAPI(epv)->C_DigestUpdate(session->handle, 1.1375 + (CK_BYTE_PTR)item->data, 1.1376 + (CK_ULONG)item->size); 1.1377 + nssSession_ExitMonitor(session); 1.1378 + return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; 1.1379 +} 1.1380 + 1.1381 +NSS_IMPLEMENT NSSItem * 1.1382 +nssToken_FinishDigest ( 1.1383 + NSSToken *tok, 1.1384 + nssSession *sessionOpt, 1.1385 + NSSItem *rvOpt, 1.1386 + NSSArena *arenaOpt 1.1387 +) 1.1388 +{ 1.1389 + CK_RV ckrv; 1.1390 + CK_ULONG digestLen; 1.1391 + CK_BYTE_PTR digest; 1.1392 + NSSItem *rvItem = NULL; 1.1393 + void *epv = nssToken_GetCryptokiEPV(tok); 1.1394 + nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; 1.1395 + 1.1396 + /* Don't ask the module to use an invalid session handle. */ 1.1397 + if (!session || session->handle == CK_INVALID_SESSION) { 1.1398 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.1399 + return NULL; 1.1400 + } 1.1401 + 1.1402 + nssSession_EnterMonitor(session); 1.1403 + ckrv = CKAPI(epv)->C_DigestFinal(session->handle, NULL, &digestLen); 1.1404 + if (ckrv != CKR_OK || digestLen == 0) { 1.1405 + nssSession_ExitMonitor(session); 1.1406 + return NULL; 1.1407 + } 1.1408 + digest = NULL; 1.1409 + if (rvOpt) { 1.1410 + if (rvOpt->size > 0 && rvOpt->size < digestLen) { 1.1411 + nssSession_ExitMonitor(session); 1.1412 + /* the error should be bad args */ 1.1413 + return NULL; 1.1414 + } 1.1415 + if (rvOpt->data) { 1.1416 + digest = rvOpt->data; 1.1417 + } 1.1418 + digestLen = rvOpt->size; 1.1419 + } 1.1420 + if (!digest) { 1.1421 + digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen); 1.1422 + if (!digest) { 1.1423 + nssSession_ExitMonitor(session); 1.1424 + return NULL; 1.1425 + } 1.1426 + } 1.1427 + ckrv = CKAPI(epv)->C_DigestFinal(session->handle, digest, &digestLen); 1.1428 + nssSession_ExitMonitor(session); 1.1429 + if (ckrv != CKR_OK) { 1.1430 + nss_ZFreeIf(digest); 1.1431 + return NULL; 1.1432 + } 1.1433 + if (!rvOpt) { 1.1434 + rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest); 1.1435 + } 1.1436 + return rvItem; 1.1437 +} 1.1438 + 1.1439 +NSS_IMPLEMENT PRBool 1.1440 +nssToken_IsPresent ( 1.1441 + NSSToken *token 1.1442 +) 1.1443 +{ 1.1444 + return nssSlot_IsTokenPresent(token->slot); 1.1445 +} 1.1446 + 1.1447 +/* Sigh. The methods to find objects declared above cause problems with 1.1448 + * the low-level object cache in the softoken -- the objects are found in 1.1449 + * toto, then one wave of GetAttributes is done, then another. Having a 1.1450 + * large number of objects causes the cache to be thrashed, as the objects 1.1451 + * are gone before there's any chance to ask for their attributes. 1.1452 + * So, for now, bringing back traversal methods for certs. This way all of 1.1453 + * the cert's attributes can be grabbed immediately after finding it, 1.1454 + * increasing the likelihood that the cache takes care of it. 1.1455 + */ 1.1456 +NSS_IMPLEMENT PRStatus 1.1457 +nssToken_TraverseCertificates ( 1.1458 + NSSToken *token, 1.1459 + nssSession *sessionOpt, 1.1460 + nssTokenSearchType searchType, 1.1461 + PRStatus (* callback)(nssCryptokiObject *instance, void *arg), 1.1462 + void *arg 1.1463 +) 1.1464 +{ 1.1465 + CK_RV ckrv; 1.1466 + CK_ULONG count; 1.1467 + CK_OBJECT_HANDLE *objectHandles; 1.1468 + CK_ATTRIBUTE_PTR attr; 1.1469 + CK_ATTRIBUTE cert_template[2]; 1.1470 + CK_ULONG ctsize; 1.1471 + NSSArena *arena; 1.1472 + PRStatus status; 1.1473 + PRUint32 arraySize, numHandles; 1.1474 + nssCryptokiObject **objects; 1.1475 + void *epv = nssToken_GetCryptokiEPV(token); 1.1476 + nssSession *session = (sessionOpt) ? sessionOpt : token->defaultSession; 1.1477 + 1.1478 + /* Don't ask the module to use an invalid session handle. */ 1.1479 + if (!session || session->handle == CK_INVALID_SESSION) { 1.1480 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.1481 + return PR_FAILURE; 1.1482 + } 1.1483 + 1.1484 + /* template for all certs */ 1.1485 + NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); 1.1486 + if (searchType == nssTokenSearchType_SessionOnly) { 1.1487 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); 1.1488 + } else if (searchType == nssTokenSearchType_TokenOnly || 1.1489 + searchType == nssTokenSearchType_TokenForced) { 1.1490 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); 1.1491 + } 1.1492 + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); 1.1493 + NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); 1.1494 + 1.1495 + /* the arena is only for the array of object handles */ 1.1496 + arena = nssArena_Create(); 1.1497 + if (!arena) { 1.1498 + return PR_FAILURE; 1.1499 + } 1.1500 + arraySize = OBJECT_STACK_SIZE; 1.1501 + numHandles = 0; 1.1502 + objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize); 1.1503 + if (!objectHandles) { 1.1504 + goto loser; 1.1505 + } 1.1506 + nssSession_EnterMonitor(session); /* ==== session lock === */ 1.1507 + /* Initialize the find with the template */ 1.1508 + ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, 1.1509 + cert_template, ctsize); 1.1510 + if (ckrv != CKR_OK) { 1.1511 + nssSession_ExitMonitor(session); 1.1512 + goto loser; 1.1513 + } 1.1514 + while (PR_TRUE) { 1.1515 + /* Issue the find for up to arraySize - numHandles objects */ 1.1516 + ckrv = CKAPI(epv)->C_FindObjects(session->handle, 1.1517 + objectHandles + numHandles, 1.1518 + arraySize - numHandles, 1.1519 + &count); 1.1520 + if (ckrv != CKR_OK) { 1.1521 + nssSession_ExitMonitor(session); 1.1522 + goto loser; 1.1523 + } 1.1524 + /* bump the number of found objects */ 1.1525 + numHandles += count; 1.1526 + if (numHandles < arraySize) { 1.1527 + break; 1.1528 + } 1.1529 + /* the array is filled, double it and continue */ 1.1530 + arraySize *= 2; 1.1531 + objectHandles = nss_ZREALLOCARRAY(objectHandles, 1.1532 + CK_OBJECT_HANDLE, 1.1533 + arraySize); 1.1534 + if (!objectHandles) { 1.1535 + nssSession_ExitMonitor(session); 1.1536 + goto loser; 1.1537 + } 1.1538 + } 1.1539 + ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle); 1.1540 + nssSession_ExitMonitor(session); /* ==== end session lock === */ 1.1541 + if (ckrv != CKR_OK) { 1.1542 + goto loser; 1.1543 + } 1.1544 + if (numHandles > 0) { 1.1545 + objects = create_objects_from_handles(token, session, 1.1546 + objectHandles, numHandles); 1.1547 + if (objects) { 1.1548 + nssCryptokiObject **op; 1.1549 + for (op = objects; *op; op++) { 1.1550 + status = (*callback)(*op, arg); 1.1551 + } 1.1552 + nss_ZFreeIf(objects); 1.1553 + } 1.1554 + } 1.1555 + nssArena_Destroy(arena); 1.1556 + return PR_SUCCESS; 1.1557 +loser: 1.1558 + nssArena_Destroy(arena); 1.1559 + return PR_FAILURE; 1.1560 +} 1.1561 + 1.1562 +NSS_IMPLEMENT PRBool 1.1563 +nssToken_IsPrivateKeyAvailable ( 1.1564 + NSSToken *token, 1.1565 + NSSCertificate *c, 1.1566 + nssCryptokiObject *instance 1.1567 +) 1.1568 +{ 1.1569 + CK_OBJECT_CLASS theClass; 1.1570 + 1.1571 + if (token == NULL) return PR_FALSE; 1.1572 + if (c == NULL) return PR_FALSE; 1.1573 + 1.1574 + theClass = CKO_PRIVATE_KEY; 1.1575 + if (!nssSlot_IsLoggedIn(token->slot)) { 1.1576 + theClass = CKO_PUBLIC_KEY; 1.1577 + } 1.1578 + if (PK11_MatchItem(token->pk11slot, instance->handle, theClass) 1.1579 + != CK_INVALID_HANDLE) { 1.1580 + return PR_TRUE; 1.1581 + } 1.1582 + return PR_FALSE; 1.1583 +}