Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1619)

Side by Side Diff: mozilla/security/nss/lib/dev/devtoken.c

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

Powered by Google App Engine
This is Rietveld 408576698