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

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

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

Powered by Google App Engine
This is Rietveld 408576698