Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/dev/devtoken.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 #include "pkcs11.h" | |
6 | |
7 #ifndef DEVM_H | |
8 #include "devm.h" | |
9 #endif /* DEVM_H */ | |
10 | |
11 #ifndef CKHELPER_H | |
12 #include "ckhelper.h" | |
13 #endif /* CKHELPER_H */ | |
14 | |
15 #include "pk11func.h" | |
16 #include "dev3hack.h" | |
17 #include "secerr.h" | |
18 | |
19 extern const NSSError NSS_ERROR_NOT_FOUND; | |
20 extern const NSSError NSS_ERROR_INVALID_ARGUMENT; | |
21 extern const NSSError NSS_ERROR_PKCS11; | |
22 | |
23 /* The number of object handles to grab during each call to C_FindObjects */ | |
24 #define OBJECT_STACK_SIZE 16 | |
25 | |
26 NSS_IMPLEMENT PRStatus | |
27 nssToken_Destroy ( | |
28 NSSToken *tok | |
29 ) | |
30 { | |
31 if (tok) { | |
32 if (PR_ATOMIC_DECREMENT(&tok->base.refCount) == 0) { | |
33 PZ_DestroyLock(tok->base.lock); | |
34 nssTokenObjectCache_Destroy(tok->cache); | |
35 /* The token holds the first/last reference to the slot. | |
36 * When the token is actually destroyed, that ref must go too. | |
37 */ | |
38 (void)nssSlot_Destroy(tok->slot); | |
39 return nssArena_Destroy(tok->base.arena); | |
40 } | |
41 } | |
42 return PR_SUCCESS; | |
43 } | |
44 | |
45 NSS_IMPLEMENT void | |
46 nssToken_Remove ( | |
47 NSSToken *tok | |
48 ) | |
49 { | |
50 nssTokenObjectCache_Clear(tok->cache); | |
51 } | |
52 | |
53 NSS_IMPLEMENT void | |
54 NSSToken_Destroy ( | |
55 NSSToken *tok | |
56 ) | |
57 { | |
58 (void)nssToken_Destroy(tok); | |
59 } | |
60 | |
61 NSS_IMPLEMENT NSSToken * | |
62 nssToken_AddRef ( | |
63 NSSToken *tok | |
64 ) | |
65 { | |
66 PR_ATOMIC_INCREMENT(&tok->base.refCount); | |
67 return tok; | |
68 } | |
69 | |
70 NSS_IMPLEMENT NSSSlot * | |
71 nssToken_GetSlot ( | |
72 NSSToken *tok | |
73 ) | |
74 { | |
75 return nssSlot_AddRef(tok->slot); | |
76 } | |
77 | |
78 NSS_IMPLEMENT void * | |
79 nssToken_GetCryptokiEPV ( | |
80 NSSToken *token | |
81 ) | |
82 { | |
83 return nssSlot_GetCryptokiEPV(token->slot); | |
84 } | |
85 | |
86 NSS_IMPLEMENT nssSession * | |
87 nssToken_GetDefaultSession ( | |
88 NSSToken *token | |
89 ) | |
90 { | |
91 return token->defaultSession; | |
92 } | |
93 | |
94 NSS_IMPLEMENT NSSUTF8 * | |
95 nssToken_GetName ( | |
96 NSSToken *tok | |
97 ) | |
98 { | |
99 if (tok == NULL) { | |
100 return ""; | |
101 } | |
102 if (tok->base.name[0] == 0) { | |
103 (void) nssSlot_IsTokenPresent(tok->slot); | |
104 } | |
105 return tok->base.name; | |
106 } | |
107 | |
108 NSS_IMPLEMENT NSSUTF8 * | |
109 NSSToken_GetName ( | |
110 NSSToken *token | |
111 ) | |
112 { | |
113 return nssToken_GetName(token); | |
114 } | |
115 | |
116 NSS_IMPLEMENT PRBool | |
117 nssToken_IsLoginRequired ( | |
118 NSSToken *token | |
119 ) | |
120 { | |
121 return (token->ckFlags & CKF_LOGIN_REQUIRED); | |
122 } | |
123 | |
124 NSS_IMPLEMENT PRBool | |
125 nssToken_NeedsPINInitialization ( | |
126 NSSToken *token | |
127 ) | |
128 { | |
129 return (!(token->ckFlags & CKF_USER_PIN_INITIALIZED)); | |
130 } | |
131 | |
132 NSS_IMPLEMENT PRStatus | |
133 nssToken_DeleteStoredObject ( | |
134 nssCryptokiObject *instance | |
135 ) | |
136 { | |
137 CK_RV ckrv; | |
138 PRStatus status; | |
139 PRBool createdSession = PR_FALSE; | |
140 NSSToken *token = instance->token; | |
141 nssSession *session = NULL; | |
142 void *epv = nssToken_GetCryptokiEPV(instance->token); | |
143 if (token->cache) { | |
144 nssTokenObjectCache_RemoveObject(token->cache, instance); | |
145 } | |
146 if (instance->isTokenObject) { | |
147 if (token->defaultSession && | |
148 nssSession_IsReadWrite(token->defaultSession)) { | |
149 session = token->defaultSession; | |
150 } else { | |
151 session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE); | |
152 createdSession = PR_TRUE; | |
153 } | |
154 } | |
155 if (session == NULL) { | |
156 return PR_FAILURE; | |
157 } | |
158 nssSession_EnterMonitor(session); | |
159 ckrv = CKAPI(epv)->C_DestroyObject(session->handle, instance->handle); | |
160 nssSession_ExitMonitor(session); | |
161 if (createdSession) { | |
162 nssSession_Destroy(session); | |
163 } | |
164 status = PR_SUCCESS; | |
165 if (ckrv != CKR_OK) { | |
166 status = PR_FAILURE; | |
167 /* use the error stack to pass the PKCS #11 error out */ | |
168 nss_SetError(ckrv); | |
169 nss_SetError(NSS_ERROR_PKCS11); | |
170 } | |
171 return status; | |
172 } | |
173 | |
174 static nssCryptokiObject * | |
175 import_object ( | |
176 NSSToken *tok, | |
177 nssSession *sessionOpt, | |
178 CK_ATTRIBUTE_PTR objectTemplate, | |
179 CK_ULONG otsize | |
180 ) | |
181 { | |
182 nssSession *session = NULL; | |
183 PRBool createdSession = PR_FALSE; | |
184 nssCryptokiObject *object = NULL; | |
185 CK_OBJECT_HANDLE handle; | |
186 CK_RV ckrv; | |
187 void *epv = nssToken_GetCryptokiEPV(tok); | |
188 if (nssCKObject_IsTokenObjectTemplate(objectTemplate, otsize)) { | |
189 if (sessionOpt) { | |
190 if (!nssSession_IsReadWrite(sessionOpt)) { | |
191 nss_SetError(NSS_ERROR_INVALID_ARGUMENT); | |
192 return NULL; | |
193 } | |
194 session = sessionOpt; | |
195 } else if (tok->defaultSession && | |
196 nssSession_IsReadWrite(tok->defaultSession)) { | |
197 session = tok->defaultSession; | |
198 } else { | |
199 session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE); | |
200 createdSession = PR_TRUE; | |
201 } | |
202 } else { | |
203 session = (sessionOpt) ? sessionOpt : tok->defaultSession; | |
204 } | |
205 if (session == NULL) { | |
206 nss_SetError(NSS_ERROR_INVALID_ARGUMENT); | |
207 return NULL; | |
208 } | |
209 nssSession_EnterMonitor(session); | |
210 ckrv = CKAPI(epv)->C_CreateObject(session->handle, | |
211 objectTemplate, otsize, | |
212 &handle); | |
213 nssSession_ExitMonitor(session); | |
214 if (ckrv == CKR_OK) { | |
215 object = nssCryptokiObject_Create(tok, session, handle); | |
216 } else { | |
217 nss_SetError(ckrv); | |
218 nss_SetError(NSS_ERROR_PKCS11); | |
219 } | |
220 if (createdSession) { | |
221 nssSession_Destroy(session); | |
222 } | |
223 return object; | |
224 } | |
225 | |
226 static nssCryptokiObject ** | |
227 create_objects_from_handles ( | |
228 NSSToken *tok, | |
229 nssSession *session, | |
230 CK_OBJECT_HANDLE *handles, | |
231 PRUint32 numH | |
232 ) | |
233 { | |
234 nssCryptokiObject **objects; | |
235 objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numH + 1); | |
236 if (objects) { | |
237 PRInt32 i; | |
238 for (i=0; i<(PRInt32)numH; i++) { | |
239 objects[i] = nssCryptokiObject_Create(tok, session, handles[i]); | |
240 if (!objects[i]) { | |
241 for (--i; i>0; --i) { | |
242 nssCryptokiObject_Destroy(objects[i]); | |
243 } | |
244 nss_ZFreeIf(objects); | |
245 objects = NULL; | |
246 break; | |
247 } | |
248 } | |
249 } | |
250 return objects; | |
251 } | |
252 | |
253 static nssCryptokiObject ** | |
254 find_objects ( | |
255 NSSToken *tok, | |
256 nssSession *sessionOpt, | |
257 CK_ATTRIBUTE_PTR obj_template, | |
258 CK_ULONG otsize, | |
259 PRUint32 maximumOpt, | |
260 PRStatus *statusOpt | |
261 ) | |
262 { | |
263 CK_RV ckrv = CKR_OK; | |
264 CK_ULONG count; | |
265 CK_OBJECT_HANDLE *objectHandles = NULL; | |
266 CK_OBJECT_HANDLE staticObjects[OBJECT_STACK_SIZE]; | |
267 PRUint32 arraySize, numHandles; | |
268 void *epv = nssToken_GetCryptokiEPV(tok); | |
269 nssCryptokiObject **objects; | |
270 nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; | |
271 | |
272 /* Don't ask the module to use an invalid session handle. */ | |
273 if (!session || session->handle == CK_INVALID_SESSION) { | |
274 ckrv = CKR_SESSION_HANDLE_INVALID; | |
275 goto loser; | |
276 } | |
277 | |
278 /* the arena is only for the array of object handles */ | |
279 if (maximumOpt > 0) { | |
280 arraySize = maximumOpt; | |
281 } else { | |
282 arraySize = OBJECT_STACK_SIZE; | |
283 } | |
284 numHandles = 0; | |
285 if (arraySize <= OBJECT_STACK_SIZE) { | |
286 objectHandles = staticObjects; | |
287 } else { | |
288 objectHandles = nss_ZNEWARRAY(NULL, CK_OBJECT_HANDLE, arraySize); | |
289 } | |
290 if (!objectHandles) { | |
291 ckrv = CKR_HOST_MEMORY; | |
292 goto loser; | |
293 } | |
294 nssSession_EnterMonitor(session); /* ==== session lock === */ | |
295 /* Initialize the find with the template */ | |
296 ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, | |
297 obj_template, otsize); | |
298 if (ckrv != CKR_OK) { | |
299 nssSession_ExitMonitor(session); | |
300 goto loser; | |
301 } | |
302 while (PR_TRUE) { | |
303 /* Issue the find for up to arraySize - numHandles objects */ | |
304 ckrv = CKAPI(epv)->C_FindObjects(session->handle, | |
305 objectHandles + numHandles, | |
306 arraySize - numHandles, | |
307 &count); | |
308 if (ckrv != CKR_OK) { | |
309 nssSession_ExitMonitor(session); | |
310 goto loser; | |
311 } | |
312 /* bump the number of found objects */ | |
313 numHandles += count; | |
314 if (maximumOpt > 0 || numHandles < arraySize) { | |
315 /* When a maximum is provided, the search is done all at once, | |
316 * so the search is finished. If the number returned was less | |
317 * than the number sought, the search is finished. | |
318 */ | |
319 break; | |
320 } | |
321 /* the array is filled, double it and continue */ | |
322 arraySize *= 2; | |
323 if (objectHandles == staticObjects) { | |
324 objectHandles = nss_ZNEWARRAY(NULL,CK_OBJECT_HANDLE, arraySize); | |
325 if (objectHandles) { | |
326 PORT_Memcpy(objectHandles, staticObjects, | |
327 OBJECT_STACK_SIZE * sizeof(objectHandles[1])); | |
328 } | |
329 } else { | |
330 objectHandles = nss_ZREALLOCARRAY(objectHandles, | |
331 CK_OBJECT_HANDLE, | |
332 arraySize); | |
333 } | |
334 if (!objectHandles) { | |
335 nssSession_ExitMonitor(session); | |
336 ckrv = CKR_HOST_MEMORY; | |
337 goto loser; | |
338 } | |
339 } | |
340 ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle); | |
341 nssSession_ExitMonitor(session); /* ==== end session lock === */ | |
342 if (ckrv != CKR_OK) { | |
343 goto loser; | |
344 } | |
345 if (numHandles > 0) { | |
346 objects = create_objects_from_handles(tok, session, | |
347 objectHandles, numHandles); | |
348 } else { | |
349 nss_SetError(NSS_ERROR_NOT_FOUND); | |
350 objects = NULL; | |
351 } | |
352 if (objectHandles && objectHandles != staticObjects) { | |
353 nss_ZFreeIf(objectHandles); | |
354 } | |
355 if (statusOpt) *statusOpt = PR_SUCCESS; | |
356 return objects; | |
357 loser: | |
358 if (objectHandles && objectHandles != staticObjects) { | |
359 nss_ZFreeIf(objectHandles); | |
360 } | |
361 /* | |
362 * These errors should be treated the same as if the objects just weren't | |
363 * found.. | |
364 */ | |
365 if ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) || | |
366 (ckrv == CKR_ATTRIBUTE_VALUE_INVALID) || | |
367 (ckrv == CKR_DATA_INVALID) || | |
368 (ckrv == CKR_DATA_LEN_RANGE) || | |
369 (ckrv == CKR_FUNCTION_NOT_SUPPORTED) || | |
370 (ckrv == CKR_TEMPLATE_INCOMPLETE) || | |
371 (ckrv == CKR_TEMPLATE_INCONSISTENT)) { | |
372 | |
373 nss_SetError(NSS_ERROR_NOT_FOUND); | |
374 if (statusOpt) *statusOpt = PR_SUCCESS; | |
375 } else { | |
376 nss_SetError(ckrv); | |
377 nss_SetError(NSS_ERROR_PKCS11); | |
378 if (statusOpt) *statusOpt = PR_FAILURE; | |
379 } | |
380 return (nssCryptokiObject **)NULL; | |
381 } | |
382 | |
383 static nssCryptokiObject ** | |
384 find_objects_by_template ( | |
385 NSSToken *token, | |
386 nssSession *sessionOpt, | |
387 CK_ATTRIBUTE_PTR obj_template, | |
388 CK_ULONG otsize, | |
389 PRUint32 maximumOpt, | |
390 PRStatus *statusOpt | |
391 ) | |
392 { | |
393 CK_OBJECT_CLASS objclass = (CK_OBJECT_CLASS)-1; | |
394 nssCryptokiObject **objects = NULL; | |
395 PRUint32 i; | |
396 | |
397 if (!token) { | |
398 PORT_SetError(SEC_ERROR_NO_TOKEN); | |
399 if (statusOpt) | |
400 *statusOpt = PR_FAILURE; | |
401 return NULL; | |
402 } | |
403 for (i=0; i<otsize; i++) { | |
404 if (obj_template[i].type == CKA_CLASS) { | |
405 objclass = *(CK_OBJECT_CLASS *)obj_template[i].pValue; | |
406 break; | |
407 } | |
408 } | |
409 PR_ASSERT(i < otsize); | |
410 if (i == otsize) { | |
411 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
412 if (statusOpt) *statusOpt = PR_FAILURE; | |
413 return NULL; | |
414 } | |
415 /* If these objects are being cached, try looking there first */ | |
416 if (token->cache && | |
417 nssTokenObjectCache_HaveObjectClass(token->cache, objclass)) | |
418 { | |
419 PRStatus status; | |
420 objects = nssTokenObjectCache_FindObjectsByTemplate(token->cache, | |
421 objclass, | |
422 obj_template, | |
423 otsize, | |
424 maximumOpt, | |
425 &status); | |
426 if (status == PR_SUCCESS) { | |
427 if (statusOpt) *statusOpt = status; | |
428 return objects; | |
429 } | |
430 } | |
431 /* Either they are not cached, or cache failed; look on token. */ | |
432 objects = find_objects(token, sessionOpt, | |
433 obj_template, otsize, | |
434 maximumOpt, statusOpt); | |
435 return objects; | |
436 } | |
437 | |
438 extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; | |
439 | |
440 NSS_IMPLEMENT nssCryptokiObject * | |
441 nssToken_ImportCertificate ( | |
442 NSSToken *tok, | |
443 nssSession *sessionOpt, | |
444 NSSCertificateType certType, | |
445 NSSItem *id, | |
446 const NSSUTF8 *nickname, | |
447 NSSDER *encoding, | |
448 NSSDER *issuer, | |
449 NSSDER *subject, | |
450 NSSDER *serial, | |
451 NSSASCII7 *email, | |
452 PRBool asTokenObject | |
453 ) | |
454 { | |
455 PRStatus status; | |
456 CK_CERTIFICATE_TYPE cert_type; | |
457 CK_ATTRIBUTE_PTR attr; | |
458 CK_ATTRIBUTE cert_tmpl[10]; | |
459 CK_ULONG ctsize; | |
460 nssTokenSearchType searchType; | |
461 nssCryptokiObject *rvObject = NULL; | |
462 | |
463 if (!tok) { | |
464 PORT_SetError(SEC_ERROR_NO_TOKEN); | |
465 return NULL; | |
466 } | |
467 if (certType == NSSCertificateType_PKIX) { | |
468 cert_type = CKC_X_509; | |
469 } else { | |
470 return (nssCryptokiObject *)NULL; | |
471 } | |
472 NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); | |
473 if (asTokenObject) { | |
474 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
475 searchType = nssTokenSearchType_TokenOnly; | |
476 } else { | |
477 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
478 searchType = nssTokenSearchType_SessionOnly; | |
479 } | |
480 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); | |
481 NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CERTIFICATE_TYPE, cert_type); | |
482 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); | |
483 NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); | |
484 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding); | |
485 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer); | |
486 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); | |
487 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial); | |
488 if (email) { | |
489 NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_EMAIL, email); | |
490 } | |
491 NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); | |
492 /* see if the cert is already there */ | |
493 rvObject = nssToken_FindCertificateByIssuerAndSerialNumber(tok, | |
494 sessionOpt, | |
495 issuer, | |
496 serial, | |
497 searchType, | |
498 NULL); | |
499 if (rvObject) { | |
500 NSSItem existingDER; | |
501 NSSSlot *slot = nssToken_GetSlot(tok); | |
502 nssSession *session = nssSlot_CreateSession(slot, NULL, PR_TRUE); | |
503 if (!session) { | |
504 nssCryptokiObject_Destroy(rvObject); | |
505 nssSlot_Destroy(slot); | |
506 return (nssCryptokiObject *)NULL; | |
507 } | |
508 /* Reject any attempt to import a new cert that has the same | |
509 * issuer/serial as an existing cert, but does not have the | |
510 * same encoding | |
511 */ | |
512 NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); | |
513 NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE); | |
514 NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); | |
515 status = nssCKObject_GetAttributes(rvObject->handle, | |
516 cert_tmpl, ctsize, NULL, | |
517 session, slot); | |
518 NSS_CK_ATTRIBUTE_TO_ITEM(cert_tmpl, &existingDER); | |
519 if (status == PR_SUCCESS) { | |
520 if (!nssItem_Equal(encoding, &existingDER, NULL)) { | |
521 nss_SetError(NSS_ERROR_INVALID_CERTIFICATE); | |
522 status = PR_FAILURE; | |
523 } | |
524 nss_ZFreeIf(existingDER.data); | |
525 } | |
526 if (status == PR_FAILURE) { | |
527 nssCryptokiObject_Destroy(rvObject); | |
528 nssSession_Destroy(session); | |
529 nssSlot_Destroy(slot); | |
530 return (nssCryptokiObject *)NULL; | |
531 } | |
532 /* according to PKCS#11, label, ID, issuer, and serial number | |
533 * may change after the object has been created. For PKIX, the | |
534 * last two attributes can't change, so for now we'll only worry | |
535 * about the first two. | |
536 */ | |
537 NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); | |
538 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); | |
539 NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); | |
540 NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); | |
541 /* reset the mutable attributes on the token */ | |
542 nssCKObject_SetAttributes(rvObject->handle, | |
543 cert_tmpl, ctsize, | |
544 session, slot); | |
545 if (!rvObject->label && nickname) { | |
546 rvObject->label = nssUTF8_Duplicate(nickname, NULL); | |
547 } | |
548 nssSession_Destroy(session); | |
549 nssSlot_Destroy(slot); | |
550 } else { | |
551 /* Import the certificate onto the token */ | |
552 rvObject = import_object(tok, sessionOpt, cert_tmpl, ctsize); | |
553 } | |
554 if (rvObject && tok->cache) { | |
555 /* The cache will overwrite the attributes if the object already | |
556 * exists. | |
557 */ | |
558 nssTokenObjectCache_ImportObject(tok->cache, rvObject, | |
559 CKO_CERTIFICATE, | |
560 cert_tmpl, ctsize); | |
561 } | |
562 return rvObject; | |
563 } | |
564 | |
565 /* traverse all objects of the given class - this should only happen | |
566 * if the token has been marked as "traversable" | |
567 */ | |
568 NSS_IMPLEMENT nssCryptokiObject ** | |
569 nssToken_FindObjects ( | |
570 NSSToken *token, | |
571 nssSession *sessionOpt, | |
572 CK_OBJECT_CLASS objclass, | |
573 nssTokenSearchType searchType, | |
574 PRUint32 maximumOpt, | |
575 PRStatus *statusOpt | |
576 ) | |
577 { | |
578 CK_ATTRIBUTE_PTR attr; | |
579 CK_ATTRIBUTE obj_template[2]; | |
580 CK_ULONG obj_size; | |
581 nssCryptokiObject **objects; | |
582 NSS_CK_TEMPLATE_START(obj_template, attr, obj_size); | |
583 /* Set the search to token/session only if provided */ | |
584 if (searchType == nssTokenSearchType_SessionOnly) { | |
585 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
586 } else if (searchType == nssTokenSearchType_TokenOnly || | |
587 searchType == nssTokenSearchType_TokenForced) { | |
588 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
589 } | |
590 NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, objclass); | |
591 NSS_CK_TEMPLATE_FINISH(obj_template, attr, obj_size); | |
592 | |
593 if (searchType == nssTokenSearchType_TokenForced) { | |
594 objects = find_objects(token, sessionOpt, | |
595 obj_template, obj_size, | |
596 maximumOpt, statusOpt); | |
597 } else { | |
598 objects = find_objects_by_template(token, sessionOpt, | |
599 obj_template, obj_size, | |
600 maximumOpt, statusOpt); | |
601 } | |
602 return objects; | |
603 } | |
604 | |
605 NSS_IMPLEMENT nssCryptokiObject ** | |
606 nssToken_FindCertificatesBySubject ( | |
607 NSSToken *token, | |
608 nssSession *sessionOpt, | |
609 NSSDER *subject, | |
610 nssTokenSearchType searchType, | |
611 PRUint32 maximumOpt, | |
612 PRStatus *statusOpt | |
613 ) | |
614 { | |
615 CK_ATTRIBUTE_PTR attr; | |
616 CK_ATTRIBUTE subj_template[3]; | |
617 CK_ULONG stsize; | |
618 nssCryptokiObject **objects; | |
619 NSS_CK_TEMPLATE_START(subj_template, attr, stsize); | |
620 /* Set the search to token/session only if provided */ | |
621 if (searchType == nssTokenSearchType_SessionOnly) { | |
622 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
623 } else if (searchType == nssTokenSearchType_TokenOnly) { | |
624 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
625 } | |
626 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); | |
627 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); | |
628 NSS_CK_TEMPLATE_FINISH(subj_template, attr, stsize); | |
629 /* now locate the token certs matching this template */ | |
630 objects = find_objects_by_template(token, sessionOpt, | |
631 subj_template, stsize, | |
632 maximumOpt, statusOpt); | |
633 return objects; | |
634 } | |
635 | |
636 NSS_IMPLEMENT nssCryptokiObject ** | |
637 nssToken_FindCertificatesByNickname ( | |
638 NSSToken *token, | |
639 nssSession *sessionOpt, | |
640 const NSSUTF8 *name, | |
641 nssTokenSearchType searchType, | |
642 PRUint32 maximumOpt, | |
643 PRStatus *statusOpt | |
644 ) | |
645 { | |
646 CK_ATTRIBUTE_PTR attr; | |
647 CK_ATTRIBUTE nick_template[3]; | |
648 CK_ULONG ntsize; | |
649 nssCryptokiObject **objects; | |
650 NSS_CK_TEMPLATE_START(nick_template, attr, ntsize); | |
651 NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, name); | |
652 /* Set the search to token/session only if provided */ | |
653 if (searchType == nssTokenSearchType_SessionOnly) { | |
654 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
655 } else if (searchType == nssTokenSearchType_TokenOnly) { | |
656 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
657 } | |
658 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); | |
659 NSS_CK_TEMPLATE_FINISH(nick_template, attr, ntsize); | |
660 /* now locate the token certs matching this template */ | |
661 objects = find_objects_by_template(token, sessionOpt, | |
662 nick_template, ntsize, | |
663 maximumOpt, statusOpt); | |
664 if (!objects) { | |
665 /* This is to workaround the fact that PKCS#11 doesn't specify | |
666 * whether the '\0' should be included. XXX Is that still true? | |
667 * im - this is not needed by the current softoken. However, I'm | |
668 * leaving it in until I have surveyed more tokens to see if it needed. | |
669 * well, its needed by the builtin token... | |
670 */ | |
671 nick_template[0].ulValueLen++; | |
672 objects = find_objects_by_template(token, sessionOpt, | |
673 nick_template, ntsize, | |
674 maximumOpt, statusOpt); | |
675 } | |
676 return objects; | |
677 } | |
678 | |
679 /* XXX | |
680 * This function *does not* use the token object cache, because not even | |
681 * the softoken will return a value for CKA_NSS_EMAIL from a call | |
682 * to GetAttributes. The softoken does allow searches with that attribute, | |
683 * it just won't return a value for it. | |
684 */ | |
685 NSS_IMPLEMENT nssCryptokiObject ** | |
686 nssToken_FindCertificatesByEmail ( | |
687 NSSToken *token, | |
688 nssSession *sessionOpt, | |
689 NSSASCII7 *email, | |
690 nssTokenSearchType searchType, | |
691 PRUint32 maximumOpt, | |
692 PRStatus *statusOpt | |
693 ) | |
694 { | |
695 CK_ATTRIBUTE_PTR attr; | |
696 CK_ATTRIBUTE email_template[3]; | |
697 CK_ULONG etsize; | |
698 nssCryptokiObject **objects; | |
699 NSS_CK_TEMPLATE_START(email_template, attr, etsize); | |
700 NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_EMAIL, email); | |
701 /* Set the search to token/session only if provided */ | |
702 if (searchType == nssTokenSearchType_SessionOnly) { | |
703 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
704 } else if (searchType == nssTokenSearchType_TokenOnly) { | |
705 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
706 } | |
707 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); | |
708 NSS_CK_TEMPLATE_FINISH(email_template, attr, etsize); | |
709 /* now locate the token certs matching this template */ | |
710 objects = find_objects(token, sessionOpt, | |
711 email_template, etsize, | |
712 maximumOpt, statusOpt); | |
713 if (!objects) { | |
714 /* This is to workaround the fact that PKCS#11 doesn't specify | |
715 * whether the '\0' should be included. XXX Is that still true? | |
716 * im - this is not needed by the current softoken. However, I'm | |
717 * leaving it in until I have surveyed more tokens to see if it needed. | |
718 * well, its needed by the builtin token... | |
719 */ | |
720 email_template[0].ulValueLen++; | |
721 objects = find_objects(token, sessionOpt, | |
722 email_template, etsize, | |
723 maximumOpt, statusOpt); | |
724 } | |
725 return objects; | |
726 } | |
727 | |
728 NSS_IMPLEMENT nssCryptokiObject ** | |
729 nssToken_FindCertificatesByID ( | |
730 NSSToken *token, | |
731 nssSession *sessionOpt, | |
732 NSSItem *id, | |
733 nssTokenSearchType searchType, | |
734 PRUint32 maximumOpt, | |
735 PRStatus *statusOpt | |
736 ) | |
737 { | |
738 CK_ATTRIBUTE_PTR attr; | |
739 CK_ATTRIBUTE id_template[3]; | |
740 CK_ULONG idtsize; | |
741 nssCryptokiObject **objects; | |
742 NSS_CK_TEMPLATE_START(id_template, attr, idtsize); | |
743 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); | |
744 /* Set the search to token/session only if provided */ | |
745 if (searchType == nssTokenSearchType_SessionOnly) { | |
746 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
747 } else if (searchType == nssTokenSearchType_TokenOnly) { | |
748 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
749 } | |
750 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); | |
751 NSS_CK_TEMPLATE_FINISH(id_template, attr, idtsize); | |
752 /* now locate the token certs matching this template */ | |
753 objects = find_objects_by_template(token, sessionOpt, | |
754 id_template, idtsize, | |
755 maximumOpt, statusOpt); | |
756 return objects; | |
757 } | |
758 | |
759 /* | |
760 * decode the serial item and return our result. | |
761 * NOTE serialDecode's data is really stored in serial. Don't free it. | |
762 */ | |
763 static PRStatus | |
764 nssToken_decodeSerialItem(NSSItem *serial, NSSItem *serialDecode) | |
765 { | |
766 unsigned char *data = (unsigned char *)serial->data; | |
767 int data_left, data_len, index; | |
768 | |
769 if ((serial->size >= 3) && (data[0] == 0x2)) { | |
770 /* remove the der encoding of the serial number before generating the | |
771 * key.. */ | |
772 data_left = serial->size-2; | |
773 data_len = data[1]; | |
774 index = 2; | |
775 | |
776 /* extended length ? (not very likely for a serial number) */ | |
777 if (data_len & 0x80) { | |
778 int len_count = data_len & 0x7f; | |
779 | |
780 data_len = 0; | |
781 data_left -= len_count; | |
782 if (data_left > 0) { | |
783 while (len_count --) { | |
784 data_len = (data_len << 8) | data[index++]; | |
785 } | |
786 } | |
787 } | |
788 /* XXX leaving any leading zeros on the serial number for backwards | |
789 * compatibility | |
790 */ | |
791 /* not a valid der, must be just an unlucky serial number value */ | |
792 if (data_len == data_left) { | |
793 serialDecode->size = data_len; | |
794 serialDecode->data = &data[index]; | |
795 return PR_SUCCESS; | |
796 } | |
797 } | |
798 return PR_FAILURE; | |
799 } | |
800 | |
801 NSS_IMPLEMENT nssCryptokiObject * | |
802 nssToken_FindCertificateByIssuerAndSerialNumber ( | |
803 NSSToken *token, | |
804 nssSession *sessionOpt, | |
805 NSSDER *issuer, | |
806 NSSDER *serial, | |
807 nssTokenSearchType searchType, | |
808 PRStatus *statusOpt | |
809 ) | |
810 { | |
811 CK_ATTRIBUTE_PTR attr; | |
812 CK_ATTRIBUTE_PTR serialAttr; | |
813 CK_ATTRIBUTE cert_template[4]; | |
814 CK_ULONG ctsize; | |
815 nssCryptokiObject **objects; | |
816 nssCryptokiObject *rvObject = NULL; | |
817 NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); | |
818 | |
819 if (!token) { | |
820 PORT_SetError(SEC_ERROR_NO_TOKEN); | |
821 if (statusOpt) | |
822 *statusOpt = PR_FAILURE; | |
823 return NULL; | |
824 } | |
825 /* Set the search to token/session only if provided */ | |
826 if (searchType == nssTokenSearchType_SessionOnly) { | |
827 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
828 } else if ((searchType == nssTokenSearchType_TokenOnly) || | |
829 (searchType == nssTokenSearchType_TokenForced)) { | |
830 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
831 } | |
832 /* Set the unique id */ | |
833 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); | |
834 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer); | |
835 serialAttr = attr; | |
836 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial); | |
837 NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); | |
838 /* get the object handle */ | |
839 if (searchType == nssTokenSearchType_TokenForced) { | |
840 objects = find_objects(token, sessionOpt, | |
841 cert_template, ctsize, | |
842 1, statusOpt); | |
843 } else { | |
844 objects = find_objects_by_template(token, sessionOpt, | |
845 cert_template, ctsize, | |
846 1, statusOpt); | |
847 } | |
848 if (objects) { | |
849 rvObject = objects[0]; | |
850 nss_ZFreeIf(objects); | |
851 } | |
852 | |
853 /* | |
854 * NSS used to incorrectly store serial numbers in their decoded form. | |
855 * because of this old tokens have decoded serial numbers. | |
856 */ | |
857 if (!objects) { | |
858 NSSItem serialDecode; | |
859 PRStatus status; | |
860 | |
861 status = nssToken_decodeSerialItem(serial, &serialDecode); | |
862 if (status != PR_SUCCESS) { | |
863 return NULL; | |
864 } | |
865 NSS_CK_SET_ATTRIBUTE_ITEM(serialAttr,CKA_SERIAL_NUMBER,&serialDecode); | |
866 if (searchType == nssTokenSearchType_TokenForced) { | |
867 objects = find_objects(token, sessionOpt, | |
868 cert_template, ctsize, | |
869 1, statusOpt); | |
870 } else { | |
871 objects = find_objects_by_template(token, sessionOpt, | |
872 cert_template, ctsize, | |
873 1, statusOpt); | |
874 } | |
875 if (objects) { | |
876 rvObject = objects[0]; | |
877 nss_ZFreeIf(objects); | |
878 } | |
879 } | |
880 return rvObject; | |
881 } | |
882 | |
883 NSS_IMPLEMENT nssCryptokiObject * | |
884 nssToken_FindCertificateByEncodedCertificate ( | |
885 NSSToken *token, | |
886 nssSession *sessionOpt, | |
887 NSSBER *encodedCertificate, | |
888 nssTokenSearchType searchType, | |
889 PRStatus *statusOpt | |
890 ) | |
891 { | |
892 CK_ATTRIBUTE_PTR attr; | |
893 CK_ATTRIBUTE cert_template[3]; | |
894 CK_ULONG ctsize; | |
895 nssCryptokiObject **objects; | |
896 nssCryptokiObject *rvObject = NULL; | |
897 NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); | |
898 /* Set the search to token/session only if provided */ | |
899 if (searchType == nssTokenSearchType_SessionOnly) { | |
900 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
901 } else if (searchType == nssTokenSearchType_TokenOnly) { | |
902 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
903 } | |
904 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); | |
905 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encodedCertificate); | |
906 NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); | |
907 /* get the object handle */ | |
908 objects = find_objects_by_template(token, sessionOpt, | |
909 cert_template, ctsize, | |
910 1, statusOpt); | |
911 if (objects) { | |
912 rvObject = objects[0]; | |
913 nss_ZFreeIf(objects); | |
914 } | |
915 return rvObject; | |
916 } | |
917 | |
918 NSS_IMPLEMENT nssCryptokiObject ** | |
919 nssToken_FindPrivateKeys ( | |
920 NSSToken *token, | |
921 nssSession *sessionOpt, | |
922 nssTokenSearchType searchType, | |
923 PRUint32 maximumOpt, | |
924 PRStatus *statusOpt | |
925 ) | |
926 { | |
927 CK_ATTRIBUTE_PTR attr; | |
928 CK_ATTRIBUTE key_template[2]; | |
929 CK_ULONG ktsize; | |
930 nssCryptokiObject **objects; | |
931 | |
932 NSS_CK_TEMPLATE_START(key_template, attr, ktsize); | |
933 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey); | |
934 if (searchType == nssTokenSearchType_SessionOnly) { | |
935 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
936 } else if (searchType == nssTokenSearchType_TokenOnly) { | |
937 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
938 } | |
939 NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); | |
940 | |
941 objects = find_objects_by_template(token, sessionOpt, | |
942 key_template, ktsize, | |
943 maximumOpt, statusOpt); | |
944 return objects; | |
945 } | |
946 | |
947 /* XXX ?there are no session cert objects, so only search token objects */ | |
948 NSS_IMPLEMENT nssCryptokiObject * | |
949 nssToken_FindPrivateKeyByID ( | |
950 NSSToken *token, | |
951 nssSession *sessionOpt, | |
952 NSSItem *keyID | |
953 ) | |
954 { | |
955 CK_ATTRIBUTE_PTR attr; | |
956 CK_ATTRIBUTE key_template[3]; | |
957 CK_ULONG ktsize; | |
958 nssCryptokiObject **objects; | |
959 nssCryptokiObject *rvKey = NULL; | |
960 | |
961 NSS_CK_TEMPLATE_START(key_template, attr, ktsize); | |
962 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey); | |
963 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
964 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID); | |
965 NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); | |
966 | |
967 objects = find_objects_by_template(token, sessionOpt, | |
968 key_template, ktsize, | |
969 1, NULL); | |
970 if (objects) { | |
971 rvKey = objects[0]; | |
972 nss_ZFreeIf(objects); | |
973 } | |
974 return rvKey; | |
975 } | |
976 | |
977 /* XXX ?there are no session cert objects, so only search token objects */ | |
978 NSS_IMPLEMENT nssCryptokiObject * | |
979 nssToken_FindPublicKeyByID ( | |
980 NSSToken *token, | |
981 nssSession *sessionOpt, | |
982 NSSItem *keyID | |
983 ) | |
984 { | |
985 CK_ATTRIBUTE_PTR attr; | |
986 CK_ATTRIBUTE key_template[3]; | |
987 CK_ULONG ktsize; | |
988 nssCryptokiObject **objects; | |
989 nssCryptokiObject *rvKey = NULL; | |
990 | |
991 NSS_CK_TEMPLATE_START(key_template, attr, ktsize); | |
992 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_pubkey); | |
993 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
994 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID); | |
995 NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); | |
996 | |
997 objects = find_objects_by_template(token, sessionOpt, | |
998 key_template, ktsize, | |
999 1, NULL); | |
1000 if (objects) { | |
1001 rvKey = objects[0]; | |
1002 nss_ZFreeIf(objects); | |
1003 } | |
1004 return rvKey; | |
1005 } | |
1006 | |
1007 static void | |
1008 sha1_hash(NSSItem *input, NSSItem *output) | |
1009 { | |
1010 NSSAlgorithmAndParameters *ap; | |
1011 PK11SlotInfo *internal = PK11_GetInternalSlot(); | |
1012 NSSToken *token = PK11Slot_GetNSSToken(internal); | |
1013 ap = NSSAlgorithmAndParameters_CreateSHA1Digest(NULL); | |
1014 (void)nssToken_Digest(token, NULL, ap, input, output, NULL); | |
1015 PK11_FreeSlot(token->pk11slot); | |
1016 nss_ZFreeIf(ap); | |
1017 } | |
1018 | |
1019 static void | |
1020 md5_hash(NSSItem *input, NSSItem *output) | |
1021 { | |
1022 NSSAlgorithmAndParameters *ap; | |
1023 PK11SlotInfo *internal = PK11_GetInternalSlot(); | |
1024 NSSToken *token = PK11Slot_GetNSSToken(internal); | |
1025 ap = NSSAlgorithmAndParameters_CreateMD5Digest(NULL); | |
1026 (void)nssToken_Digest(token, NULL, ap, input, output, NULL); | |
1027 PK11_FreeSlot(token->pk11slot); | |
1028 nss_ZFreeIf(ap); | |
1029 } | |
1030 | |
1031 static CK_TRUST | |
1032 get_ck_trust ( | |
1033 nssTrustLevel nssTrust | |
1034 ) | |
1035 { | |
1036 CK_TRUST t; | |
1037 switch (nssTrust) { | |
1038 case nssTrustLevel_NotTrusted: t = CKT_NSS_NOT_TRUSTED; break; | |
1039 case nssTrustLevel_TrustedDelegator: t = CKT_NSS_TRUSTED_DELEGATOR; | |
1040 break; | |
1041 case nssTrustLevel_ValidDelegator: t = CKT_NSS_VALID_DELEGATOR; break; | |
1042 case nssTrustLevel_Trusted: t = CKT_NSS_TRUSTED; break; | |
1043 case nssTrustLevel_MustVerify: t = CKT_NSS_MUST_VERIFY_TRUST; break; | |
1044 case nssTrustLevel_Unknown: | |
1045 default: t = CKT_NSS_TRUST_UNKNOWN; break; | |
1046 } | |
1047 return t; | |
1048 } | |
1049 | |
1050 NSS_IMPLEMENT nssCryptokiObject * | |
1051 nssToken_ImportTrust ( | |
1052 NSSToken *tok, | |
1053 nssSession *sessionOpt, | |
1054 NSSDER *certEncoding, | |
1055 NSSDER *certIssuer, | |
1056 NSSDER *certSerial, | |
1057 nssTrustLevel serverAuth, | |
1058 nssTrustLevel clientAuth, | |
1059 nssTrustLevel codeSigning, | |
1060 nssTrustLevel emailProtection, | |
1061 PRBool stepUpApproved, | |
1062 PRBool asTokenObject | |
1063 ) | |
1064 { | |
1065 nssCryptokiObject *object; | |
1066 CK_OBJECT_CLASS tobjc = CKO_NSS_TRUST; | |
1067 CK_TRUST ckSA, ckCA, ckCS, ckEP; | |
1068 CK_ATTRIBUTE_PTR attr; | |
1069 CK_ATTRIBUTE trust_tmpl[11]; | |
1070 CK_ULONG tsize; | |
1071 PRUint8 sha1[20]; /* this is cheating... */ | |
1072 PRUint8 md5[16]; | |
1073 NSSItem sha1_result, md5_result; | |
1074 sha1_result.data = sha1; sha1_result.size = sizeof sha1; | |
1075 md5_result.data = md5; md5_result.size = sizeof md5; | |
1076 sha1_hash(certEncoding, &sha1_result); | |
1077 md5_hash(certEncoding, &md5_result); | |
1078 ckSA = get_ck_trust(serverAuth); | |
1079 ckCA = get_ck_trust(clientAuth); | |
1080 ckCS = get_ck_trust(codeSigning); | |
1081 ckEP = get_ck_trust(emailProtection); | |
1082 NSS_CK_TEMPLATE_START(trust_tmpl, attr, tsize); | |
1083 if (asTokenObject) { | |
1084 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
1085 } else { | |
1086 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
1087 } | |
1088 NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); | |
1089 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer); | |
1090 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, certSerial); | |
1091 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result); | |
1092 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_MD5_HASH, &md5_result); | |
1093 /* now set the trust values */ | |
1094 NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, ckSA); | |
1095 NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, ckCA); | |
1096 NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, ckCS); | |
1097 NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, ckEP); | |
1098 if (stepUpApproved) { | |
1099 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TRUST_STEP_UP_APPROVED, | |
1100 &g_ck_true); | |
1101 } else { | |
1102 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TRUST_STEP_UP_APPROVED, | |
1103 &g_ck_false); | |
1104 } | |
1105 NSS_CK_TEMPLATE_FINISH(trust_tmpl, attr, tsize); | |
1106 /* import the trust object onto the token */ | |
1107 object = import_object(tok, sessionOpt, trust_tmpl, tsize); | |
1108 if (object && tok->cache) { | |
1109 nssTokenObjectCache_ImportObject(tok->cache, object, tobjc, | |
1110 trust_tmpl, tsize); | |
1111 } | |
1112 return object; | |
1113 } | |
1114 | |
1115 NSS_IMPLEMENT nssCryptokiObject * | |
1116 nssToken_FindTrustForCertificate ( | |
1117 NSSToken *token, | |
1118 nssSession *sessionOpt, | |
1119 NSSDER *certEncoding, | |
1120 NSSDER *certIssuer, | |
1121 NSSDER *certSerial, | |
1122 nssTokenSearchType searchType | |
1123 ) | |
1124 { | |
1125 CK_OBJECT_CLASS tobjc = CKO_NSS_TRUST; | |
1126 CK_ATTRIBUTE_PTR attr; | |
1127 CK_ATTRIBUTE tobj_template[5]; | |
1128 CK_ULONG tobj_size; | |
1129 nssSession *session = sessionOpt ? sessionOpt : token->defaultSession; | |
1130 nssCryptokiObject *object = NULL, **objects; | |
1131 | |
1132 /* Don't ask the module to use an invalid session handle. */ | |
1133 if (!session || session->handle == CK_INVALID_SESSION) { | |
1134 PORT_SetError(SEC_ERROR_NO_TOKEN); | |
1135 return object; | |
1136 } | |
1137 | |
1138 NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size); | |
1139 if (searchType == nssTokenSearchType_TokenOnly) { | |
1140 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
1141 } | |
1142 NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); | |
1143 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer); | |
1144 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER , certSerial); | |
1145 NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size); | |
1146 objects = find_objects_by_template(token, session, | |
1147 tobj_template, tobj_size, | |
1148 1, NULL); | |
1149 if (objects) { | |
1150 object = objects[0]; | |
1151 nss_ZFreeIf(objects); | |
1152 } | |
1153 return object; | |
1154 } | |
1155 | |
1156 NSS_IMPLEMENT nssCryptokiObject * | |
1157 nssToken_ImportCRL ( | |
1158 NSSToken *token, | |
1159 nssSession *sessionOpt, | |
1160 NSSDER *subject, | |
1161 NSSDER *encoding, | |
1162 PRBool isKRL, | |
1163 NSSUTF8 *url, | |
1164 PRBool asTokenObject | |
1165 ) | |
1166 { | |
1167 nssCryptokiObject *object; | |
1168 CK_OBJECT_CLASS crlobjc = CKO_NSS_CRL; | |
1169 CK_ATTRIBUTE_PTR attr; | |
1170 CK_ATTRIBUTE crl_tmpl[6]; | |
1171 CK_ULONG crlsize; | |
1172 | |
1173 NSS_CK_TEMPLATE_START(crl_tmpl, attr, crlsize); | |
1174 if (asTokenObject) { | |
1175 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
1176 } else { | |
1177 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
1178 } | |
1179 NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc); | |
1180 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); | |
1181 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding); | |
1182 NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_URL, url); | |
1183 if (isKRL) { | |
1184 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NSS_KRL, &g_ck_true); | |
1185 } else { | |
1186 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NSS_KRL, &g_ck_false); | |
1187 } | |
1188 NSS_CK_TEMPLATE_FINISH(crl_tmpl, attr, crlsize); | |
1189 | |
1190 /* import the crl object onto the token */ | |
1191 object = import_object(token, sessionOpt, crl_tmpl, crlsize); | |
1192 if (object && token->cache) { | |
1193 nssTokenObjectCache_ImportObject(token->cache, object, crlobjc, | |
1194 crl_tmpl, crlsize); | |
1195 } | |
1196 return object; | |
1197 } | |
1198 | |
1199 NSS_IMPLEMENT nssCryptokiObject ** | |
1200 nssToken_FindCRLsBySubject ( | |
1201 NSSToken *token, | |
1202 nssSession *sessionOpt, | |
1203 NSSDER *subject, | |
1204 nssTokenSearchType searchType, | |
1205 PRUint32 maximumOpt, | |
1206 PRStatus *statusOpt | |
1207 ) | |
1208 { | |
1209 CK_OBJECT_CLASS crlobjc = CKO_NSS_CRL; | |
1210 CK_ATTRIBUTE_PTR attr; | |
1211 CK_ATTRIBUTE crlobj_template[3]; | |
1212 CK_ULONG crlobj_size; | |
1213 nssCryptokiObject **objects = NULL; | |
1214 nssSession *session = sessionOpt ? sessionOpt : token->defaultSession; | |
1215 | |
1216 /* Don't ask the module to use an invalid session handle. */ | |
1217 if (!session || session->handle == CK_INVALID_SESSION) { | |
1218 PORT_SetError(SEC_ERROR_NO_TOKEN); | |
1219 return objects; | |
1220 } | |
1221 | |
1222 NSS_CK_TEMPLATE_START(crlobj_template, attr, crlobj_size); | |
1223 if (searchType == nssTokenSearchType_SessionOnly) { | |
1224 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
1225 } else if (searchType == nssTokenSearchType_TokenOnly || | |
1226 searchType == nssTokenSearchType_TokenForced) { | |
1227 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
1228 } | |
1229 NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc); | |
1230 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); | |
1231 NSS_CK_TEMPLATE_FINISH(crlobj_template, attr, crlobj_size); | |
1232 | |
1233 objects = find_objects_by_template(token, session, | |
1234 crlobj_template, crlobj_size, | |
1235 maximumOpt, statusOpt); | |
1236 return objects; | |
1237 } | |
1238 | |
1239 NSS_IMPLEMENT PRStatus | |
1240 nssToken_GetCachedObjectAttributes ( | |
1241 NSSToken *token, | |
1242 NSSArena *arenaOpt, | |
1243 nssCryptokiObject *object, | |
1244 CK_OBJECT_CLASS objclass, | |
1245 CK_ATTRIBUTE_PTR atemplate, | |
1246 CK_ULONG atlen | |
1247 ) | |
1248 { | |
1249 if (!token->cache) { | |
1250 return PR_FAILURE; | |
1251 } | |
1252 return nssTokenObjectCache_GetObjectAttributes(token->cache, arenaOpt, | |
1253 object, objclass, | |
1254 atemplate, atlen); | |
1255 } | |
1256 | |
1257 NSS_IMPLEMENT NSSItem * | |
1258 nssToken_Digest ( | |
1259 NSSToken *tok, | |
1260 nssSession *sessionOpt, | |
1261 NSSAlgorithmAndParameters *ap, | |
1262 NSSItem *data, | |
1263 NSSItem *rvOpt, | |
1264 NSSArena *arenaOpt | |
1265 ) | |
1266 { | |
1267 CK_RV ckrv; | |
1268 CK_ULONG digestLen; | |
1269 CK_BYTE_PTR digest; | |
1270 NSSItem *rvItem = NULL; | |
1271 void *epv = nssToken_GetCryptokiEPV(tok); | |
1272 nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; | |
1273 | |
1274 /* Don't ask the module to use an invalid session handle. */ | |
1275 if (!session || session->handle == CK_INVALID_SESSION) { | |
1276 PORT_SetError(SEC_ERROR_NO_TOKEN); | |
1277 return rvItem; | |
1278 } | |
1279 | |
1280 nssSession_EnterMonitor(session); | |
1281 ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism); | |
1282 if (ckrv != CKR_OK) { | |
1283 nssSession_ExitMonitor(session); | |
1284 return NULL; | |
1285 } | |
1286 #if 0 | |
1287 /* XXX the standard says this should work, but it doesn't */ | |
1288 ckrv = CKAPI(epv)->C_Digest(session->handle, NULL, 0, NULL, &digestLen); | |
1289 if (ckrv != CKR_OK) { | |
1290 nssSession_ExitMonitor(session); | |
1291 return NULL; | |
1292 } | |
1293 #endif | |
1294 digestLen = 0; /* XXX for now */ | |
1295 digest = NULL; | |
1296 if (rvOpt) { | |
1297 if (rvOpt->size > 0 && rvOpt->size < digestLen) { | |
1298 nssSession_ExitMonitor(session); | |
1299 /* the error should be bad args */ | |
1300 return NULL; | |
1301 } | |
1302 if (rvOpt->data) { | |
1303 digest = rvOpt->data; | |
1304 } | |
1305 digestLen = rvOpt->size; | |
1306 } | |
1307 if (!digest) { | |
1308 digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen); | |
1309 if (!digest) { | |
1310 nssSession_ExitMonitor(session); | |
1311 return NULL; | |
1312 } | |
1313 } | |
1314 ckrv = CKAPI(epv)->C_Digest(session->handle, | |
1315 (CK_BYTE_PTR)data->data, | |
1316 (CK_ULONG)data->size, | |
1317 (CK_BYTE_PTR)digest, | |
1318 &digestLen); | |
1319 nssSession_ExitMonitor(session); | |
1320 if (ckrv != CKR_OK) { | |
1321 nss_ZFreeIf(digest); | |
1322 return NULL; | |
1323 } | |
1324 if (!rvOpt) { | |
1325 rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest); | |
1326 } | |
1327 return rvItem; | |
1328 } | |
1329 | |
1330 NSS_IMPLEMENT PRStatus | |
1331 nssToken_BeginDigest ( | |
1332 NSSToken *tok, | |
1333 nssSession *sessionOpt, | |
1334 NSSAlgorithmAndParameters *ap | |
1335 ) | |
1336 { | |
1337 CK_RV ckrv; | |
1338 void *epv = nssToken_GetCryptokiEPV(tok); | |
1339 nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; | |
1340 | |
1341 /* Don't ask the module to use an invalid session handle. */ | |
1342 if (!session || session->handle == CK_INVALID_SESSION) { | |
1343 PORT_SetError(SEC_ERROR_NO_TOKEN); | |
1344 return PR_FAILURE; | |
1345 } | |
1346 | |
1347 nssSession_EnterMonitor(session); | |
1348 ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism); | |
1349 nssSession_ExitMonitor(session); | |
1350 return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; | |
1351 } | |
1352 | |
1353 NSS_IMPLEMENT PRStatus | |
1354 nssToken_ContinueDigest ( | |
1355 NSSToken *tok, | |
1356 nssSession *sessionOpt, | |
1357 NSSItem *item | |
1358 ) | |
1359 { | |
1360 CK_RV ckrv; | |
1361 void *epv = nssToken_GetCryptokiEPV(tok); | |
1362 nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; | |
1363 | |
1364 /* Don't ask the module to use an invalid session handle. */ | |
1365 if (!session || session->handle == CK_INVALID_SESSION) { | |
1366 PORT_SetError(SEC_ERROR_NO_TOKEN); | |
1367 return PR_FAILURE; | |
1368 } | |
1369 | |
1370 nssSession_EnterMonitor(session); | |
1371 ckrv = CKAPI(epv)->C_DigestUpdate(session->handle, | |
1372 (CK_BYTE_PTR)item->data, | |
1373 (CK_ULONG)item->size); | |
1374 nssSession_ExitMonitor(session); | |
1375 return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; | |
1376 } | |
1377 | |
1378 NSS_IMPLEMENT NSSItem * | |
1379 nssToken_FinishDigest ( | |
1380 NSSToken *tok, | |
1381 nssSession *sessionOpt, | |
1382 NSSItem *rvOpt, | |
1383 NSSArena *arenaOpt | |
1384 ) | |
1385 { | |
1386 CK_RV ckrv; | |
1387 CK_ULONG digestLen; | |
1388 CK_BYTE_PTR digest; | |
1389 NSSItem *rvItem = NULL; | |
1390 void *epv = nssToken_GetCryptokiEPV(tok); | |
1391 nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; | |
1392 | |
1393 /* Don't ask the module to use an invalid session handle. */ | |
1394 if (!session || session->handle == CK_INVALID_SESSION) { | |
1395 PORT_SetError(SEC_ERROR_NO_TOKEN); | |
1396 return NULL; | |
1397 } | |
1398 | |
1399 nssSession_EnterMonitor(session); | |
1400 ckrv = CKAPI(epv)->C_DigestFinal(session->handle, NULL, &digestLen); | |
1401 if (ckrv != CKR_OK || digestLen == 0) { | |
1402 nssSession_ExitMonitor(session); | |
1403 return NULL; | |
1404 } | |
1405 digest = NULL; | |
1406 if (rvOpt) { | |
1407 if (rvOpt->size > 0 && rvOpt->size < digestLen) { | |
1408 nssSession_ExitMonitor(session); | |
1409 /* the error should be bad args */ | |
1410 return NULL; | |
1411 } | |
1412 if (rvOpt->data) { | |
1413 digest = rvOpt->data; | |
1414 } | |
1415 digestLen = rvOpt->size; | |
1416 } | |
1417 if (!digest) { | |
1418 digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen); | |
1419 if (!digest) { | |
1420 nssSession_ExitMonitor(session); | |
1421 return NULL; | |
1422 } | |
1423 } | |
1424 ckrv = CKAPI(epv)->C_DigestFinal(session->handle, digest, &digestLen); | |
1425 nssSession_ExitMonitor(session); | |
1426 if (ckrv != CKR_OK) { | |
1427 nss_ZFreeIf(digest); | |
1428 return NULL; | |
1429 } | |
1430 if (!rvOpt) { | |
1431 rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest); | |
1432 } | |
1433 return rvItem; | |
1434 } | |
1435 | |
1436 NSS_IMPLEMENT PRBool | |
1437 nssToken_IsPresent ( | |
1438 NSSToken *token | |
1439 ) | |
1440 { | |
1441 return nssSlot_IsTokenPresent(token->slot); | |
1442 } | |
1443 | |
1444 /* Sigh. The methods to find objects declared above cause problems with | |
1445 * the low-level object cache in the softoken -- the objects are found in | |
1446 * toto, then one wave of GetAttributes is done, then another. Having a | |
1447 * large number of objects causes the cache to be thrashed, as the objects | |
1448 * are gone before there's any chance to ask for their attributes. | |
1449 * So, for now, bringing back traversal methods for certs. This way all of | |
1450 * the cert's attributes can be grabbed immediately after finding it, | |
1451 * increasing the likelihood that the cache takes care of it. | |
1452 */ | |
1453 NSS_IMPLEMENT PRStatus | |
1454 nssToken_TraverseCertificates ( | |
1455 NSSToken *token, | |
1456 nssSession *sessionOpt, | |
1457 nssTokenSearchType searchType, | |
1458 PRStatus (* callback)(nssCryptokiObject *instance, void *arg), | |
1459 void *arg | |
1460 ) | |
1461 { | |
1462 CK_RV ckrv; | |
1463 CK_ULONG count; | |
1464 CK_OBJECT_HANDLE *objectHandles; | |
1465 CK_ATTRIBUTE_PTR attr; | |
1466 CK_ATTRIBUTE cert_template[2]; | |
1467 CK_ULONG ctsize; | |
1468 NSSArena *arena; | |
1469 PRStatus status; | |
1470 PRUint32 arraySize, numHandles; | |
1471 nssCryptokiObject **objects; | |
1472 void *epv = nssToken_GetCryptokiEPV(token); | |
1473 nssSession *session = (sessionOpt) ? sessionOpt : token->defaultSession; | |
1474 | |
1475 /* Don't ask the module to use an invalid session handle. */ | |
1476 if (!session || session->handle == CK_INVALID_SESSION) { | |
1477 PORT_SetError(SEC_ERROR_NO_TOKEN); | |
1478 return PR_FAILURE; | |
1479 } | |
1480 | |
1481 /* template for all certs */ | |
1482 NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); | |
1483 if (searchType == nssTokenSearchType_SessionOnly) { | |
1484 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); | |
1485 } else if (searchType == nssTokenSearchType_TokenOnly || | |
1486 searchType == nssTokenSearchType_TokenForced) { | |
1487 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); | |
1488 } | |
1489 NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); | |
1490 NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); | |
1491 | |
1492 /* the arena is only for the array of object handles */ | |
1493 arena = nssArena_Create(); | |
1494 if (!arena) { | |
1495 return PR_FAILURE; | |
1496 } | |
1497 arraySize = OBJECT_STACK_SIZE; | |
1498 numHandles = 0; | |
1499 objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize); | |
1500 if (!objectHandles) { | |
1501 goto loser; | |
1502 } | |
1503 nssSession_EnterMonitor(session); /* ==== session lock === */ | |
1504 /* Initialize the find with the template */ | |
1505 ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, | |
1506 cert_template, ctsize); | |
1507 if (ckrv != CKR_OK) { | |
1508 nssSession_ExitMonitor(session); | |
1509 goto loser; | |
1510 } | |
1511 while (PR_TRUE) { | |
1512 /* Issue the find for up to arraySize - numHandles objects */ | |
1513 ckrv = CKAPI(epv)->C_FindObjects(session->handle, | |
1514 objectHandles + numHandles, | |
1515 arraySize - numHandles, | |
1516 &count); | |
1517 if (ckrv != CKR_OK) { | |
1518 nssSession_ExitMonitor(session); | |
1519 goto loser; | |
1520 } | |
1521 /* bump the number of found objects */ | |
1522 numHandles += count; | |
1523 if (numHandles < arraySize) { | |
1524 break; | |
1525 } | |
1526 /* the array is filled, double it and continue */ | |
1527 arraySize *= 2; | |
1528 objectHandles = nss_ZREALLOCARRAY(objectHandles, | |
1529 CK_OBJECT_HANDLE, | |
1530 arraySize); | |
1531 if (!objectHandles) { | |
1532 nssSession_ExitMonitor(session); | |
1533 goto loser; | |
1534 } | |
1535 } | |
1536 ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle); | |
1537 nssSession_ExitMonitor(session); /* ==== end session lock === */ | |
1538 if (ckrv != CKR_OK) { | |
1539 goto loser; | |
1540 } | |
1541 if (numHandles > 0) { | |
1542 objects = create_objects_from_handles(token, session, | |
1543 objectHandles, numHandles); | |
1544 if (objects) { | |
1545 nssCryptokiObject **op; | |
1546 for (op = objects; *op; op++) { | |
1547 status = (*callback)(*op, arg); | |
1548 } | |
1549 nss_ZFreeIf(objects); | |
1550 } | |
1551 } | |
1552 nssArena_Destroy(arena); | |
1553 return PR_SUCCESS; | |
1554 loser: | |
1555 nssArena_Destroy(arena); | |
1556 return PR_FAILURE; | |
1557 } | |
1558 | |
1559 NSS_IMPLEMENT PRBool | |
1560 nssToken_IsPrivateKeyAvailable ( | |
1561 NSSToken *token, | |
1562 NSSCertificate *c, | |
1563 nssCryptokiObject *instance | |
1564 ) | |
1565 { | |
1566 CK_OBJECT_CLASS theClass; | |
1567 | |
1568 if (token == NULL) return PR_FALSE; | |
1569 if (c == NULL) return PR_FALSE; | |
1570 | |
1571 theClass = CKO_PRIVATE_KEY; | |
1572 if (!nssSlot_IsLoggedIn(token->slot)) { | |
1573 theClass = CKO_PUBLIC_KEY; | |
1574 } | |
1575 if (PK11_MatchItem(token->pk11slot, instance->handle, theClass) | |
1576 != CK_INVALID_HANDLE) { | |
1577 return PR_TRUE; | |
1578 } | |
1579 return PR_FALSE; | |
1580 } |