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

Side by Side Diff: nss/lib/softoken/pkcs11u.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/softoken/pkcs11ni.h ('k') | nss/lib/softoken/sdb.h » ('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 * Internal PKCS #11 functions. Should only be called by pkcs11.c
6 */
7 #include "pkcs11.h"
8 #include "pkcs11i.h"
9 #include "lowkeyi.h"
10 #include "secasn1.h"
11 #include "blapi.h"
12 #include "secerr.h"
13 #include "prnetdb.h" /* for PR_ntohl */
14 #include "sftkdb.h"
15 #include "softoken.h"
16
17 /*
18 * ******************** Attribute Utilities *******************************
19 */
20
21 /*
22 * create a new attribute with type, value, and length. Space is allocated
23 * to hold value.
24 */
25 static SFTKAttribute *
26 sftk_NewAttribute(SFTKObject *object,
27 CK_ATTRIBUTE_TYPE type, const void *value, CK_ULONG len)
28 {
29 SFTKAttribute *attribute;
30
31 SFTKSessionObject *so = sftk_narrowToSessionObject(object);
32 int index;
33
34 if (so == NULL) {
35 /* allocate new attribute in a buffer */
36 PORT_Assert(0);
37 return NULL;
38 }
39 /*
40 * We attempt to keep down contention on Malloc and Arena locks by
41 * limiting the number of these calls on high traversed paths. This
42 * is done for attributes by 'allocating' them from a pool already
43 * allocated by the parent object.
44 */
45 PZ_Lock(so->attributeLock);
46 index = so->nextAttr++;
47 PZ_Unlock(so->attributeLock);
48 PORT_Assert(index < MAX_OBJS_ATTRS);
49 if (index >= MAX_OBJS_ATTRS) return NULL;
50
51 attribute = &so->attrList[index];
52 attribute->attrib.type = type;
53 attribute->freeAttr = PR_FALSE;
54 attribute->freeData = PR_FALSE;
55 if (value) {
56 if (len <= ATTR_SPACE) {
57 attribute->attrib.pValue = attribute->space;
58 } else {
59 attribute->attrib.pValue = PORT_Alloc(len);
60 attribute->freeData = PR_TRUE;
61 }
62 if (attribute->attrib.pValue == NULL) {
63 return NULL;
64 }
65 PORT_Memcpy(attribute->attrib.pValue,value,len);
66 attribute->attrib.ulValueLen = len;
67 } else {
68 attribute->attrib.pValue = NULL;
69 attribute->attrib.ulValueLen = 0;
70 }
71 attribute->attrib.type = type;
72 attribute->handle = type;
73 attribute->next = attribute->prev = NULL;
74 return attribute;
75 }
76
77 /*
78 * Free up all the memory associated with an attribute. Reference count
79 * must be zero to call this.
80 */
81 static void
82 sftk_DestroyAttribute(SFTKAttribute *attribute)
83 {
84 if (attribute->freeData) {
85 if (attribute->attrib.pValue) {
86 /* clear out the data in the attribute value... it may have been
87 * sensitive data */
88 PORT_Memset(attribute->attrib.pValue, 0,
89 attribute->attrib.ulValueLen);
90 }
91 PORT_Free(attribute->attrib.pValue);
92 }
93 PORT_Free(attribute);
94 }
95
96 /*
97 * release a reference to an attribute structure
98 */
99 void
100 sftk_FreeAttribute(SFTKAttribute *attribute)
101 {
102 if (attribute->freeAttr) {
103 sftk_DestroyAttribute(attribute);
104 return;
105 }
106 }
107
108 static SFTKAttribute *
109 sftk_FindTokenAttribute(SFTKTokenObject *object,CK_ATTRIBUTE_TYPE type)
110 {
111 SFTKAttribute *myattribute = NULL;
112 SFTKDBHandle *dbHandle = NULL;
113 CK_RV crv = CKR_HOST_MEMORY;
114
115 myattribute = (SFTKAttribute*)PORT_Alloc(sizeof(SFTKAttribute));
116 if (myattribute == NULL) {
117 goto loser;
118 }
119
120 dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle);
121
122 myattribute->handle = type;
123 myattribute->attrib.type = type;
124 myattribute->attrib.pValue = myattribute->space;
125 myattribute->attrib.ulValueLen = ATTR_SPACE;
126 myattribute->next = myattribute->prev = NULL;
127 myattribute->freeAttr = PR_TRUE;
128 myattribute->freeData = PR_FALSE;
129
130 crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
131 &myattribute->attrib, 1);
132
133 /* attribute is bigger than our attribute space buffer, malloc it */
134 if (crv == CKR_BUFFER_TOO_SMALL) {
135 myattribute->attrib.pValue = NULL;
136 crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
137 &myattribute->attrib, 1);
138 if (crv != CKR_OK) {
139 goto loser;
140 }
141 myattribute->attrib.pValue = PORT_Alloc(myattribute->attrib.ulValueLen);
142 if (myattribute->attrib.pValue == NULL) {
143 crv = CKR_HOST_MEMORY;
144 goto loser;
145 }
146 myattribute->freeData = PR_TRUE;
147 crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
148 &myattribute->attrib, 1);
149 }
150 loser:
151 if (dbHandle) {
152 sftk_freeDB(dbHandle);
153 }
154 if (crv != CKR_OK) {
155 if (myattribute) {
156 myattribute->attrib.ulValueLen = 0;
157 sftk_FreeAttribute(myattribute);
158 myattribute = NULL;
159 }
160 }
161 return myattribute;
162 }
163
164 /*
165 * look up and attribute structure from a type and Object structure.
166 * The returned attribute is referenced and needs to be freed when
167 * it is no longer needed.
168 */
169 SFTKAttribute *
170 sftk_FindAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
171 {
172 SFTKAttribute *attribute;
173 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
174
175 if (sessObject == NULL) {
176 return sftk_FindTokenAttribute(sftk_narrowToTokenObject(object),type);
177 }
178
179 PZ_Lock(sessObject->attributeLock);
180 sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize);
181 PZ_Unlock(sessObject->attributeLock);
182
183 return(attribute);
184 }
185
186 /*
187 * Take a buffer and it's length and return it's true size in bits;
188 */
189 unsigned int
190 sftk_GetLengthInBits(unsigned char *buf, unsigned int bufLen)
191 {
192 unsigned int size = bufLen * 8;
193 unsigned int i;
194
195 /* Get the real length in bytes */
196 for (i=0; i < bufLen; i++) {
197 unsigned char c = *buf++;
198 if (c != 0) {
199 unsigned char m;
200 for (m=0x80; m > 0 ; m = m >> 1) {
201 if ((c & m) != 0) {
202 break;
203 }
204 size--;
205 }
206 break;
207 }
208 size-=8;
209 }
210 return size;
211 }
212
213 /*
214 * Constrain a big num attribute. to size and padding
215 * minLength means length of the object must be greater than equal to minLength
216 * maxLength means length of the object must be less than equal to maxLength
217 * minMultiple means that object length mod minMultiple must equal 0.
218 * all input sizes are in bits.
219 * if any constraint is '0' that constraint is not checked.
220 */
221 CK_RV
222 sftk_ConstrainAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
223 int minLength, int maxLength, int minMultiple)
224 {
225 SFTKAttribute *attribute;
226 int size;
227 unsigned char *ptr;
228
229 attribute = sftk_FindAttribute(object, type);
230 if (!attribute) {
231 return CKR_TEMPLATE_INCOMPLETE;
232 }
233 ptr = (unsigned char *) attribute->attrib.pValue;
234 if (ptr == NULL) {
235 sftk_FreeAttribute(attribute);
236 return CKR_ATTRIBUTE_VALUE_INVALID;
237 }
238 size = sftk_GetLengthInBits(ptr, attribute->attrib.ulValueLen);
239 sftk_FreeAttribute(attribute);
240
241 if ((minLength != 0) && (size < minLength)) {
242 return CKR_ATTRIBUTE_VALUE_INVALID;
243 }
244 if ((maxLength != 0) && (size > maxLength)) {
245 return CKR_ATTRIBUTE_VALUE_INVALID;
246 }
247 if ((minMultiple != 0) && ((size % minMultiple) != 0)) {
248 return CKR_ATTRIBUTE_VALUE_INVALID;
249 }
250 return CKR_OK;
251 }
252
253 PRBool
254 sftk_hasAttributeToken(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
255 {
256 CK_ATTRIBUTE template;
257 CK_RV crv;
258 SFTKDBHandle *dbHandle;
259
260 dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle);
261 template.type = type;
262 template.pValue = NULL;
263 template.ulValueLen = 0;
264
265 crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, &template, 1);
266 sftk_freeDB(dbHandle);
267
268 /* attribute is bigger than our attribute space buffer, malloc it */
269 return (crv == CKR_OK) ? PR_TRUE : PR_FALSE;
270 }
271
272 /*
273 * return true if object has attribute
274 */
275 PRBool
276 sftk_hasAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
277 {
278 SFTKAttribute *attribute;
279 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
280
281 if (sessObject == NULL) {
282 return sftk_hasAttributeToken(sftk_narrowToTokenObject(object), type);
283 }
284
285 PZ_Lock(sessObject->attributeLock);
286 sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize);
287 PZ_Unlock(sessObject->attributeLock);
288
289 return (PRBool)(attribute != NULL);
290 }
291
292 /*
293 * add an attribute to an object
294 */
295 static void
296 sftk_AddAttribute(SFTKObject *object,SFTKAttribute *attribute)
297 {
298 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
299
300 if (sessObject == NULL) return;
301 PZ_Lock(sessObject->attributeLock);
302 sftkqueue_add(attribute,attribute->handle,
303 sessObject->head, sessObject->hashSize);
304 PZ_Unlock(sessObject->attributeLock);
305 }
306
307 /*
308 * copy an unsigned attribute into a SECItem. Secitem is allocated in
309 * the specified arena.
310 */
311 CK_RV
312 sftk_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object,
313 CK_ATTRIBUTE_TYPE type)
314 {
315 SFTKAttribute *attribute;
316
317 item->data = NULL;
318
319 attribute = sftk_FindAttribute(object, type);
320 if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
321
322 (void)SECITEM_AllocItem(arena, item, attribute->attrib.ulValueLen);
323 if (item->data == NULL) {
324 sftk_FreeAttribute(attribute);
325 return CKR_HOST_MEMORY;
326 }
327 PORT_Memcpy(item->data, attribute->attrib.pValue, item->len);
328 sftk_FreeAttribute(attribute);
329 return CKR_OK;
330 }
331
332 /*
333 * fetch multiple attributes into SECItems. Secitem data is allocated in
334 * the specified arena.
335 */
336 CK_RV
337 sftk_MultipleAttribute2SecItem(PLArenaPool *arena, SFTKObject *object,
338 SFTKItemTemplate *itemTemplate, int itemTemplateCount)
339 {
340
341 CK_RV crv = CKR_OK;
342 CK_ATTRIBUTE templateSpace[SFTK_MAX_ITEM_TEMPLATE];
343 CK_ATTRIBUTE *template;
344 SFTKTokenObject *tokObject;
345 SFTKDBHandle *dbHandle = NULL;
346 int i;
347
348 tokObject = sftk_narrowToTokenObject(object);
349
350 /* session objects, just loop through the list */
351 if (tokObject == NULL) {
352 for (i=0; i < itemTemplateCount; i++) {
353 crv = sftk_Attribute2SecItem(arena,itemTemplate[i].item, object,
354 itemTemplate[i].type);
355 if (crv != CKR_OK) {
356 return crv;
357 }
358 }
359 return CKR_OK;
360 }
361
362 /* don't do any work if none is required */
363 if (itemTemplateCount == 0) {
364 return CKR_OK;
365 }
366
367 /* don't allocate the template unless we need it */
368 if (itemTemplateCount > SFTK_MAX_ITEM_TEMPLATE) {
369 template = PORT_NewArray(CK_ATTRIBUTE, itemTemplateCount);
370 } else {
371 template = templateSpace;
372 }
373
374 if (template == NULL) {
375 crv = CKR_HOST_MEMORY;
376 goto loser;
377 }
378
379 dbHandle = sftk_getDBForTokenObject(object->slot, object->handle);
380 if (dbHandle == NULL) {
381 crv = CKR_OBJECT_HANDLE_INVALID;
382 goto loser;
383 }
384
385 /* set up the PKCS #11 template */
386 for (i=0; i < itemTemplateCount; i++) {
387 template[i].type = itemTemplate[i].type;
388 template[i].pValue = NULL;
389 template[i].ulValueLen = 0;
390 }
391
392 /* fetch the attribute lengths */
393 crv = sftkdb_GetAttributeValue(dbHandle, object->handle,
394 template, itemTemplateCount);
395 if (crv != CKR_OK) {
396 goto loser;
397 }
398
399 /* allocate space for the attributes */
400 for (i=0; i < itemTemplateCount ; i++) {
401 template[i].pValue = PORT_ArenaAlloc(arena, template[i].ulValueLen);
402 if (template[i].pValue == NULL) {
403 crv = CKR_HOST_MEMORY;
404 goto loser;
405 }
406 }
407
408 /* fetch the attributes */
409 crv = sftkdb_GetAttributeValue(dbHandle, object->handle,
410 template, itemTemplateCount);
411 if (crv != CKR_OK) {
412 goto loser;
413 }
414
415 /* Fill in the items */
416 for (i=0; i < itemTemplateCount; i++) {
417 itemTemplate[i].item->data = template[i].pValue;
418 itemTemplate[i].item->len = template[i].ulValueLen;
419 }
420
421 loser:
422 if (template != templateSpace) {
423 PORT_Free(template);
424 }
425 if (dbHandle) {
426 sftk_freeDB(dbHandle);
427 }
428
429 return crv;
430 }
431
432
433 /*
434 * delete an attribute from an object
435 */
436 static void
437 sftk_DeleteAttribute(SFTKObject *object, SFTKAttribute *attribute)
438 {
439 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
440
441 if (sessObject == NULL) {
442 return ;
443 }
444 PZ_Lock(sessObject->attributeLock);
445 if (sftkqueue_is_queued(attribute,attribute->handle,
446 sessObject->head, sessObject->hashSize)) {
447 sftkqueue_delete(attribute,attribute->handle,
448 sessObject->head, sessObject->hashSize);
449 }
450 PZ_Unlock(sessObject->attributeLock);
451 }
452
453 /*
454 * this is only valid for CK_BBOOL type attributes. Return the state
455 * of that attribute.
456 */
457 PRBool
458 sftk_isTrue(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
459 {
460 SFTKAttribute *attribute;
461 PRBool tok = PR_FALSE;
462
463 attribute=sftk_FindAttribute(object,type);
464 if (attribute == NULL) { return PR_FALSE; }
465 tok = (PRBool)(*(CK_BBOOL *)attribute->attrib.pValue);
466 sftk_FreeAttribute(attribute);
467
468 return tok;
469 }
470
471 /*
472 * force an attribute to null.
473 * this is for sensitive keys which are stored in the database, we don't
474 * want to keep this info around in memory in the clear.
475 */
476 void
477 sftk_nullAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
478 {
479 SFTKAttribute *attribute;
480
481 attribute=sftk_FindAttribute(object,type);
482 if (attribute == NULL) return;
483
484 if (attribute->attrib.pValue != NULL) {
485 PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
486 if (attribute->freeData) {
487 PORT_Free(attribute->attrib.pValue);
488 }
489 attribute->freeData = PR_FALSE;
490 attribute->attrib.pValue = NULL;
491 attribute->attrib.ulValueLen = 0;
492 }
493 sftk_FreeAttribute(attribute);
494 }
495
496
497 static CK_RV
498 sftk_forceTokenAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type,
499 const void *value, unsigned int len)
500 {
501 CK_ATTRIBUTE attribute;
502 SFTKDBHandle *dbHandle = NULL;
503 SFTKTokenObject *to = sftk_narrowToTokenObject(object);
504 CK_RV crv;
505
506 PORT_Assert(to);
507 if (to == NULL) {
508 return CKR_DEVICE_ERROR;
509 }
510
511 dbHandle = sftk_getDBForTokenObject(object->slot, object->handle);
512
513 attribute.type = type;
514 attribute.pValue = (void *)value;
515 attribute.ulValueLen = len;
516
517 crv = sftkdb_SetAttributeValue(dbHandle, object, &attribute, 1);
518 sftk_freeDB(dbHandle);
519 return crv;
520 }
521
522 /*
523 * force an attribute to a specifc value.
524 */
525 CK_RV
526 sftk_forceAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type,
527 const void *value, unsigned int len)
528 {
529 SFTKAttribute *attribute;
530 void *att_val = NULL;
531 PRBool freeData = PR_FALSE;
532
533 PORT_Assert(object);
534 PORT_Assert(object->refCount);
535 PORT_Assert(object->slot);
536 if (!object ||
537 !object->refCount ||
538 !object->slot) {
539 return CKR_DEVICE_ERROR;
540 }
541 if (sftk_isToken(object->handle)) {
542 return sftk_forceTokenAttribute(object,type,value,len);
543 }
544 attribute=sftk_FindAttribute(object,type);
545 if (attribute == NULL) return sftk_AddAttributeType(object,type,value,len);
546
547
548 if (value) {
549 if (len <= ATTR_SPACE) {
550 att_val = attribute->space;
551 } else {
552 att_val = PORT_Alloc(len);
553 freeData = PR_TRUE;
554 }
555 if (att_val == NULL) {
556 return CKR_HOST_MEMORY;
557 }
558 if (attribute->attrib.pValue == att_val) {
559 PORT_Memset(attribute->attrib.pValue,0,
560 attribute->attrib.ulValueLen);
561 }
562 PORT_Memcpy(att_val,value,len);
563 }
564 if (attribute->attrib.pValue != NULL) {
565 if (attribute->attrib.pValue != att_val) {
566 PORT_Memset(attribute->attrib.pValue,0,
567 attribute->attrib.ulValueLen);
568 }
569 if (attribute->freeData) {
570 PORT_Free(attribute->attrib.pValue);
571 }
572 attribute->freeData = PR_FALSE;
573 attribute->attrib.pValue = NULL;
574 attribute->attrib.ulValueLen = 0;
575 }
576 if (att_val) {
577 attribute->attrib.pValue = att_val;
578 attribute->attrib.ulValueLen = len;
579 attribute->freeData = freeData;
580 }
581 sftk_FreeAttribute(attribute);
582 return CKR_OK;
583 }
584
585 /*
586 * return a null terminated string from attribute 'type'. This string
587 * is allocated and needs to be freed with PORT_Free() When complete.
588 */
589 char *
590 sftk_getString(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
591 {
592 SFTKAttribute *attribute;
593 char *label = NULL;
594
595 attribute=sftk_FindAttribute(object,type);
596 if (attribute == NULL) return NULL;
597
598 if (attribute->attrib.pValue != NULL) {
599 label = (char *) PORT_Alloc(attribute->attrib.ulValueLen+1);
600 if (label == NULL) {
601 sftk_FreeAttribute(attribute);
602 return NULL;
603 }
604
605 PORT_Memcpy(label,attribute->attrib.pValue,
606 attribute->attrib.ulValueLen);
607 label[attribute->attrib.ulValueLen] = 0;
608 }
609 sftk_FreeAttribute(attribute);
610 return label;
611 }
612
613 /*
614 * decode when a particular attribute may be modified
615 * SFTK_NEVER: This attribute must be set at object creation time and
616 * can never be modified.
617 * SFTK_ONCOPY: This attribute may be modified only when you copy the
618 * object.
619 * SFTK_SENSITIVE: The CKA_SENSITIVE attribute can only be changed from
620 * CK_FALSE to CK_TRUE.
621 * SFTK_ALWAYS: This attribute can always be modified.
622 * Some attributes vary their modification type based on the class of the
623 * object.
624 */
625 SFTKModifyType
626 sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
627 {
628 /* if we don't know about it, user user defined, always allow modify */
629 SFTKModifyType mtype = SFTK_ALWAYS;
630
631 switch(type) {
632 /* NEVER */
633 case CKA_CLASS:
634 case CKA_CERTIFICATE_TYPE:
635 case CKA_KEY_TYPE:
636 case CKA_MODULUS:
637 case CKA_MODULUS_BITS:
638 case CKA_PUBLIC_EXPONENT:
639 case CKA_PRIVATE_EXPONENT:
640 case CKA_PRIME:
641 case CKA_SUBPRIME:
642 case CKA_BASE:
643 case CKA_PRIME_1:
644 case CKA_PRIME_2:
645 case CKA_EXPONENT_1:
646 case CKA_EXPONENT_2:
647 case CKA_COEFFICIENT:
648 case CKA_VALUE_LEN:
649 case CKA_ALWAYS_SENSITIVE:
650 case CKA_NEVER_EXTRACTABLE:
651 case CKA_NETSCAPE_DB:
652 mtype = SFTK_NEVER;
653 break;
654
655 /* ONCOPY */
656 case CKA_TOKEN:
657 case CKA_PRIVATE:
658 case CKA_MODIFIABLE:
659 mtype = SFTK_ONCOPY;
660 break;
661
662 /* SENSITIVE */
663 case CKA_SENSITIVE:
664 case CKA_EXTRACTABLE:
665 mtype = SFTK_SENSITIVE;
666 break;
667
668 /* ALWAYS */
669 case CKA_LABEL:
670 case CKA_APPLICATION:
671 case CKA_ID:
672 case CKA_SERIAL_NUMBER:
673 case CKA_START_DATE:
674 case CKA_END_DATE:
675 case CKA_DERIVE:
676 case CKA_ENCRYPT:
677 case CKA_DECRYPT:
678 case CKA_SIGN:
679 case CKA_VERIFY:
680 case CKA_SIGN_RECOVER:
681 case CKA_VERIFY_RECOVER:
682 case CKA_WRAP:
683 case CKA_UNWRAP:
684 mtype = SFTK_ALWAYS;
685 break;
686
687 /* DEPENDS ON CLASS */
688 case CKA_VALUE:
689 mtype = (inClass == CKO_DATA) ? SFTK_ALWAYS : SFTK_NEVER;
690 break;
691
692 case CKA_SUBJECT:
693 mtype = (inClass == CKO_CERTIFICATE) ? SFTK_NEVER : SFTK_ALWAYS;
694 break;
695 default:
696 break;
697 }
698 return mtype;
699 }
700
701 /* decode if a particular attribute is sensitive (cannot be read
702 * back to the user of if the object is set to SENSITIVE) */
703 PRBool
704 sftk_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
705 {
706 switch(type) {
707 /* ALWAYS */
708 case CKA_PRIVATE_EXPONENT:
709 case CKA_PRIME_1:
710 case CKA_PRIME_2:
711 case CKA_EXPONENT_1:
712 case CKA_EXPONENT_2:
713 case CKA_COEFFICIENT:
714 return PR_TRUE;
715
716 /* DEPENDS ON CLASS */
717 case CKA_VALUE:
718 /* PRIVATE and SECRET KEYS have SENSITIVE values */
719 return (PRBool)((inClass == CKO_PRIVATE_KEY) || (inClass == CKO_SECRET_K EY));
720
721 default:
722 break;
723 }
724 return PR_FALSE;
725 }
726
727 /*
728 * copy an attribute into a SECItem. Secitem is allocated in the specified
729 * arena.
730 */
731 CK_RV
732 sftk_Attribute2SecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object,
733 CK_ATTRIBUTE_TYPE type)
734 {
735 int len;
736 SFTKAttribute *attribute;
737
738 attribute = sftk_FindAttribute(object, type);
739 if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
740 len = attribute->attrib.ulValueLen;
741
742 if (arena) {
743 item->data = (unsigned char *) PORT_ArenaAlloc(arena,len);
744 } else {
745 item->data = (unsigned char *) PORT_Alloc(len);
746 }
747 if (item->data == NULL) {
748 sftk_FreeAttribute(attribute);
749 return CKR_HOST_MEMORY;
750 }
751 item->len = len;
752 PORT_Memcpy(item->data,attribute->attrib.pValue, len);
753 sftk_FreeAttribute(attribute);
754 return CKR_OK;
755 }
756
757 CK_RV
758 sftk_GetULongAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
759 CK_ULONG *longData)
760 {
761 SFTKAttribute *attribute;
762
763 attribute = sftk_FindAttribute(object, type);
764 if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
765
766 if (attribute->attrib.ulValueLen != sizeof(CK_ULONG)) {
767 return CKR_ATTRIBUTE_VALUE_INVALID;
768 }
769
770 *longData = *(CK_ULONG *)attribute->attrib.pValue;
771 sftk_FreeAttribute(attribute);
772 return CKR_OK;
773 }
774
775 void
776 sftk_DeleteAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
777 {
778 SFTKAttribute *attribute;
779 attribute = sftk_FindAttribute(object, type);
780 if (attribute == NULL) return ;
781 sftk_DeleteAttribute(object,attribute);
782 sftk_FreeAttribute(attribute);
783 }
784
785 CK_RV
786 sftk_AddAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type,
787 const void *valPtr, CK_ULONG length)
788 {
789 SFTKAttribute *attribute;
790 attribute = sftk_NewAttribute(object,type,valPtr,length);
791 if (attribute == NULL) { return CKR_HOST_MEMORY; }
792 sftk_AddAttribute(object,attribute);
793 return CKR_OK;
794 }
795
796 /*
797 * ******************** Object Utilities *******************************
798 */
799
800 /* must be called holding sftk_tokenKeyLock(slot) */
801 static SECItem *
802 sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
803 {
804 return (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)handle);
805 }
806
807 /*
808 * use the refLock. This operations should be very rare, so the added
809 * contention on the ref lock should be lower than the overhead of adding
810 * a new lock. We use separate functions for this just in case I'm wrong.
811 */
812 static void
813 sftk_tokenKeyLock(SFTKSlot *slot) {
814 SKIP_AFTER_FORK(PZ_Lock(slot->objectLock));
815 }
816
817 static void
818 sftk_tokenKeyUnlock(SFTKSlot *slot) {
819 SKIP_AFTER_FORK(PZ_Unlock(slot->objectLock));
820 }
821
822 static PRIntn
823 sftk_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg)
824 {
825 SECItem *item = (SECItem *)entry->value;
826
827 SECITEM_FreeItem(item, PR_TRUE);
828 return HT_ENUMERATE_NEXT;
829 }
830
831 CK_RV
832 SFTK_ClearTokenKeyHashTable(SFTKSlot *slot)
833 {
834 sftk_tokenKeyLock(slot);
835 PORT_Assert(!slot->present);
836 PL_HashTableEnumerateEntries(slot->tokObjHashTable, sftk_freeHashItem, NULL) ;
837 sftk_tokenKeyUnlock(slot);
838 return CKR_OK;
839 }
840
841
842 /* allocation hooks that allow us to recycle old object structures */
843 static SFTKObjectFreeList sessionObjectList = { NULL, NULL, 0 };
844 static SFTKObjectFreeList tokenObjectList = { NULL, NULL, 0 };
845
846 SFTKObject *
847 sftk_GetObjectFromList(PRBool *hasLocks, PRBool optimizeSpace,
848 SFTKObjectFreeList *list, unsigned int hashSize, PRBool isSessionObject)
849 {
850 SFTKObject *object;
851 int size = 0;
852
853 if (!optimizeSpace) {
854 PZ_Lock(list->lock);
855 object = list->head;
856 if (object) {
857 list->head = object->next;
858 list->count--;
859 }
860 PZ_Unlock(list->lock);
861 if (object) {
862 object->next = object->prev = NULL;
863 *hasLocks = PR_TRUE;
864 return object;
865 }
866 }
867 size = isSessionObject ? sizeof(SFTKSessionObject)
868 + hashSize *sizeof(SFTKAttribute *) : sizeof(SFTKTokenObject);
869
870 object = (SFTKObject*)PORT_ZAlloc(size);
871 if (isSessionObject && object) {
872 ((SFTKSessionObject *)object)->hashSize = hashSize;
873 }
874 *hasLocks = PR_FALSE;
875 return object;
876 }
877
878 static void
879 sftk_PutObjectToList(SFTKObject *object, SFTKObjectFreeList *list,
880 PRBool isSessionObject) {
881
882 /* the code below is equivalent to :
883 * optimizeSpace = isSessionObject ? object->optimizeSpace : PR_FALSE;
884 * just faster.
885 */
886 PRBool optimizeSpace = isSessionObject &&
887 ((SFTKSessionObject *)object)->optimizeSpace;
888 if (object->refLock && !optimizeSpace
889 && (list->count < MAX_OBJECT_LIST_SIZE)) {
890 PZ_Lock(list->lock);
891 object->next = list->head;
892 list->head = object;
893 list->count++;
894 PZ_Unlock(list->lock);
895 return;
896 }
897 if (isSessionObject) {
898 SFTKSessionObject *so = (SFTKSessionObject *)object;
899 PZ_DestroyLock(so->attributeLock);
900 so->attributeLock = NULL;
901 }
902 if (object->refLock) {
903 PZ_DestroyLock(object->refLock);
904 object->refLock = NULL;
905 }
906 PORT_Free(object);
907 }
908
909 static SFTKObject *
910 sftk_freeObjectData(SFTKObject *object) {
911 SFTKObject *next = object->next;
912
913 PORT_Free(object);
914 return next;
915 }
916
917 static void
918 sftk_InitFreeList(SFTKObjectFreeList *list)
919 {
920 list->lock = PZ_NewLock(nssILockObject);
921 }
922
923 void sftk_InitFreeLists(void)
924 {
925 sftk_InitFreeList(&sessionObjectList);
926 sftk_InitFreeList(&tokenObjectList);
927 }
928
929 static void
930 sftk_CleanupFreeList(SFTKObjectFreeList *list, PRBool isSessionList)
931 {
932 SFTKObject *object;
933
934 if (!list->lock) {
935 return;
936 }
937 SKIP_AFTER_FORK(PZ_Lock(list->lock));
938 for (object= list->head; object != NULL;
939 object = sftk_freeObjectData(object)) {
940 PZ_DestroyLock(object->refLock);
941 if (isSessionList) {
942 PZ_DestroyLock(((SFTKSessionObject *)object)->attributeLock);
943 }
944 }
945 list->count = 0;
946 list->head = NULL;
947 SKIP_AFTER_FORK(PZ_Unlock(list->lock));
948 SKIP_AFTER_FORK(PZ_DestroyLock(list->lock));
949 list->lock = NULL;
950 }
951
952 void
953 sftk_CleanupFreeLists(void)
954 {
955 sftk_CleanupFreeList(&sessionObjectList, PR_TRUE);
956 sftk_CleanupFreeList(&tokenObjectList, PR_FALSE);
957 }
958
959
960 /*
961 * Create a new object
962 */
963 SFTKObject *
964 sftk_NewObject(SFTKSlot *slot)
965 {
966 SFTKObject *object;
967 SFTKSessionObject *sessObject;
968 PRBool hasLocks = PR_FALSE;
969 unsigned int i;
970 unsigned int hashSize = 0;
971
972 hashSize = (slot->optimizeSpace) ? SPACE_ATTRIBUTE_HASH_SIZE :
973 TIME_ATTRIBUTE_HASH_SIZE;
974
975 object = sftk_GetObjectFromList(&hasLocks, slot->optimizeSpace,
976 &sessionObjectList, hashSize, PR_TRUE);
977 if (object == NULL) {
978 return NULL;
979 }
980 sessObject = (SFTKSessionObject *)object;
981 sessObject->nextAttr = 0;
982
983 for (i=0; i < MAX_OBJS_ATTRS; i++) {
984 sessObject->attrList[i].attrib.pValue = NULL;
985 sessObject->attrList[i].freeData = PR_FALSE;
986 }
987 sessObject->optimizeSpace = slot->optimizeSpace;
988
989 object->handle = 0;
990 object->next = object->prev = NULL;
991 object->slot = slot;
992
993 object->refCount = 1;
994 sessObject->sessionList.next = NULL;
995 sessObject->sessionList.prev = NULL;
996 sessObject->sessionList.parent = object;
997 sessObject->session = NULL;
998 sessObject->wasDerived = PR_FALSE;
999 if (!hasLocks) object->refLock = PZ_NewLock(nssILockRefLock);
1000 if (object->refLock == NULL) {
1001 PORT_Free(object);
1002 return NULL;
1003 }
1004 if (!hasLocks) sessObject->attributeLock = PZ_NewLock(nssILockAttribute);
1005 if (sessObject->attributeLock == NULL) {
1006 PZ_DestroyLock(object->refLock);
1007 PORT_Free(object);
1008 return NULL;
1009 }
1010 for (i=0; i < sessObject->hashSize; i++) {
1011 sessObject->head[i] = NULL;
1012 }
1013 object->objectInfo = NULL;
1014 object->infoFree = NULL;
1015 return object;
1016 }
1017
1018 static CK_RV
1019 sftk_DestroySessionObjectData(SFTKSessionObject *so)
1020 {
1021 int i;
1022
1023 for (i=0; i < MAX_OBJS_ATTRS; i++) {
1024 unsigned char *value = so->attrList[i].attrib.pValue;
1025 if (value) {
1026 PORT_Memset(value,0,so->attrList[i].attrib.ulValueLen);
1027 if (so->attrList[i].freeData) {
1028 PORT_Free(value);
1029 }
1030 so->attrList[i].attrib.pValue = NULL;
1031 so->attrList[i].freeData = PR_FALSE;
1032 }
1033 }
1034 /* PZ_DestroyLock(so->attributeLock);*/
1035 return CKR_OK;
1036 }
1037
1038 /*
1039 * free all the data associated with an object. Object reference count must
1040 * be 'zero'.
1041 */
1042 static CK_RV
1043 sftk_DestroyObject(SFTKObject *object)
1044 {
1045 CK_RV crv = CKR_OK;
1046 SFTKSessionObject *so = sftk_narrowToSessionObject(object);
1047 SFTKTokenObject *to = sftk_narrowToTokenObject(object);
1048
1049 PORT_Assert(object->refCount == 0);
1050
1051 /* delete the database value */
1052 if (to) {
1053 if (to->dbKey.data) {
1054 PORT_Free(to->dbKey.data);
1055 to->dbKey.data = NULL;
1056 }
1057 }
1058 if (so) {
1059 sftk_DestroySessionObjectData(so);
1060 }
1061 if (object->objectInfo) {
1062 (*object->infoFree)(object->objectInfo);
1063 object->objectInfo = NULL;
1064 object->infoFree = NULL;
1065 }
1066 if (so) {
1067 sftk_PutObjectToList(object,&sessionObjectList,PR_TRUE);
1068 } else {
1069 sftk_PutObjectToList(object,&tokenObjectList,PR_FALSE);
1070 }
1071 return crv;
1072 }
1073
1074 void
1075 sftk_ReferenceObject(SFTKObject *object)
1076 {
1077 PZ_Lock(object->refLock);
1078 object->refCount++;
1079 PZ_Unlock(object->refLock);
1080 }
1081
1082 static SFTKObject *
1083 sftk_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, SFTKSlot *slot)
1084 {
1085 SFTKObject *object;
1086 PRUint32 index = sftk_hash(handle, slot->sessObjHashSize);
1087
1088 if (sftk_isToken(handle)) {
1089 return sftk_NewTokenObject(slot, NULL, handle);
1090 }
1091
1092 PZ_Lock(slot->objectLock);
1093 sftkqueue_find2(object, handle, index, slot->sessObjHashTable);
1094 if (object) {
1095 sftk_ReferenceObject(object);
1096 }
1097 PZ_Unlock(slot->objectLock);
1098
1099 return(object);
1100 }
1101 /*
1102 * look up and object structure from a handle. OBJECT_Handles only make
1103 * sense in terms of a given session. make a reference to that object
1104 * structure returned.
1105 */
1106 SFTKObject *
1107 sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle, SFTKSession *session)
1108 {
1109 SFTKSlot *slot = sftk_SlotFromSession(session);
1110
1111 return sftk_ObjectFromHandleOnSlot(handle,slot);
1112 }
1113
1114
1115 /*
1116 * release a reference to an object handle
1117 */
1118 SFTKFreeStatus
1119 sftk_FreeObject(SFTKObject *object)
1120 {
1121 PRBool destroy = PR_FALSE;
1122 CK_RV crv;
1123
1124 PZ_Lock(object->refLock);
1125 if (object->refCount == 1) destroy = PR_TRUE;
1126 object->refCount--;
1127 PZ_Unlock(object->refLock);
1128
1129 if (destroy) {
1130 crv = sftk_DestroyObject(object);
1131 if (crv != CKR_OK) {
1132 return SFTK_DestroyFailure;
1133 }
1134 return SFTK_Destroyed;
1135 }
1136 return SFTK_Busy;
1137 }
1138
1139 /*
1140 * add an object to a slot and session queue. These two functions
1141 * adopt the object.
1142 */
1143 void
1144 sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object)
1145 {
1146 PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize);
1147 sftkqueue_init_element(object);
1148 PZ_Lock(slot->objectLock);
1149 sftkqueue_add2(object, object->handle, index, slot->sessObjHashTable);
1150 PZ_Unlock(slot->objectLock);
1151 }
1152
1153 void
1154 sftk_AddObject(SFTKSession *session, SFTKObject *object)
1155 {
1156 SFTKSlot *slot = sftk_SlotFromSession(session);
1157 SFTKSessionObject *so = sftk_narrowToSessionObject(object);
1158
1159 if (so) {
1160 PZ_Lock(session->objectLock);
1161 sftkqueue_add(&so->sessionList,0,session->objects,0);
1162 so->session = session;
1163 PZ_Unlock(session->objectLock);
1164 }
1165 sftk_AddSlotObject(slot,object);
1166 sftk_ReferenceObject(object);
1167 }
1168
1169 /*
1170 * delete an object from a slot and session queue
1171 */
1172 CK_RV
1173 sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
1174 {
1175 SFTKSlot *slot = sftk_SlotFromSession(session);
1176 SFTKSessionObject *so = sftk_narrowToSessionObject(object);
1177 CK_RV crv = CKR_OK;
1178 PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize);
1179
1180 /* Handle Token case */
1181 if (so && so->session) {
1182 SFTKSession *session = so->session;
1183 PZ_Lock(session->objectLock);
1184 sftkqueue_delete(&so->sessionList,0,session->objects,0);
1185 PZ_Unlock(session->objectLock);
1186 PZ_Lock(slot->objectLock);
1187 sftkqueue_delete2(object, object->handle, index, slot->sessObjHashTable) ;
1188 PZ_Unlock(slot->objectLock);
1189 sftkqueue_clear_deleted_element(object);
1190 sftk_FreeObject(object); /* free the reference owned by the queue */
1191 } else {
1192 SFTKDBHandle *handle = sftk_getDBForTokenObject(slot, object->handle);
1193 #ifdef DEBUG
1194 SFTKTokenObject *to = sftk_narrowToTokenObject(object);
1195 PORT_Assert(to);
1196 #endif
1197 crv = sftkdb_DestroyObject(handle, object->handle);
1198 sftk_freeDB(handle);
1199 }
1200 return crv;
1201 }
1202
1203 /*
1204 * Token objects don't explicitly store their attributes, so we need to know
1205 * what attributes make up a particular token object before we can copy it.
1206 * below are the tables by object type.
1207 */
1208 static const CK_ATTRIBUTE_TYPE commonAttrs[] = {
1209 CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_MODIFIABLE
1210 };
1211 static const CK_ULONG commonAttrsCount =
1212 sizeof(commonAttrs)/sizeof(commonAttrs[0]);
1213
1214 static const CK_ATTRIBUTE_TYPE commonKeyAttrs[] = {
1215 CKA_ID, CKA_START_DATE, CKA_END_DATE, CKA_DERIVE, CKA_LOCAL, CKA_KEY_TYPE
1216 };
1217 static const CK_ULONG commonKeyAttrsCount =
1218 sizeof(commonKeyAttrs)/sizeof(commonKeyAttrs[0]);
1219
1220 static const CK_ATTRIBUTE_TYPE secretKeyAttrs[] = {
1221 CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN,
1222 CKA_VERIFY, CKA_WRAP, CKA_UNWRAP, CKA_VALUE
1223 };
1224 static const CK_ULONG secretKeyAttrsCount =
1225 sizeof(secretKeyAttrs)/sizeof(secretKeyAttrs[0]);
1226
1227 static const CK_ATTRIBUTE_TYPE commonPubKeyAttrs[] = {
1228 CKA_ENCRYPT, CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_WRAP, CKA_SUBJECT
1229 };
1230 static const CK_ULONG commonPubKeyAttrsCount =
1231 sizeof(commonPubKeyAttrs)/sizeof(commonPubKeyAttrs[0]);
1232
1233 static const CK_ATTRIBUTE_TYPE rsaPubKeyAttrs[] = {
1234 CKA_MODULUS, CKA_PUBLIC_EXPONENT
1235 };
1236 static const CK_ULONG rsaPubKeyAttrsCount =
1237 sizeof(rsaPubKeyAttrs)/sizeof(rsaPubKeyAttrs[0]);
1238
1239 static const CK_ATTRIBUTE_TYPE dsaPubKeyAttrs[] = {
1240 CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE
1241 };
1242 static const CK_ULONG dsaPubKeyAttrsCount =
1243 sizeof(dsaPubKeyAttrs)/sizeof(dsaPubKeyAttrs[0]);
1244
1245 static const CK_ATTRIBUTE_TYPE dhPubKeyAttrs[] = {
1246 CKA_PRIME, CKA_BASE, CKA_VALUE
1247 };
1248 static const CK_ULONG dhPubKeyAttrsCount =
1249 sizeof(dhPubKeyAttrs)/sizeof(dhPubKeyAttrs[0]);
1250 #ifndef NSS_DISABLE_ECC
1251 static const CK_ATTRIBUTE_TYPE ecPubKeyAttrs[] = {
1252 CKA_EC_PARAMS, CKA_EC_POINT
1253 };
1254 static const CK_ULONG ecPubKeyAttrsCount =
1255 sizeof(ecPubKeyAttrs)/sizeof(ecPubKeyAttrs[0]);
1256 #endif
1257
1258 static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = {
1259 CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_UNWRAP, CKA_SUBJECT,
1260 CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB
1261 };
1262 static const CK_ULONG commonPrivKeyAttrsCount =
1263 sizeof(commonPrivKeyAttrs)/sizeof(commonPrivKeyAttrs[0]);
1264
1265 static const CK_ATTRIBUTE_TYPE rsaPrivKeyAttrs[] = {
1266 CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT,
1267 CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT
1268 };
1269 static const CK_ULONG rsaPrivKeyAttrsCount =
1270 sizeof(rsaPrivKeyAttrs)/sizeof(rsaPrivKeyAttrs[0]);
1271
1272 static const CK_ATTRIBUTE_TYPE dsaPrivKeyAttrs[] = {
1273 CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE
1274 };
1275 static const CK_ULONG dsaPrivKeyAttrsCount =
1276 sizeof(dsaPrivKeyAttrs)/sizeof(dsaPrivKeyAttrs[0]);
1277
1278 static const CK_ATTRIBUTE_TYPE dhPrivKeyAttrs[] = {
1279 CKA_PRIME, CKA_BASE, CKA_VALUE
1280 };
1281 static const CK_ULONG dhPrivKeyAttrsCount =
1282 sizeof(dhPrivKeyAttrs)/sizeof(dhPrivKeyAttrs[0]);
1283 #ifndef NSS_DISABLE_ECC
1284 static const CK_ATTRIBUTE_TYPE ecPrivKeyAttrs[] = {
1285 CKA_EC_PARAMS, CKA_VALUE
1286 };
1287 static const CK_ULONG ecPrivKeyAttrsCount =
1288 sizeof(ecPrivKeyAttrs)/sizeof(ecPrivKeyAttrs[0]);
1289 #endif
1290
1291 static const CK_ATTRIBUTE_TYPE certAttrs[] = {
1292 CKA_CERTIFICATE_TYPE, CKA_VALUE, CKA_SUBJECT, CKA_ISSUER, CKA_SERIAL_NUMBER
1293 };
1294 static const CK_ULONG certAttrsCount =
1295 sizeof(certAttrs)/sizeof(certAttrs[0]);
1296
1297 static const CK_ATTRIBUTE_TYPE trustAttrs[] = {
1298 CKA_ISSUER, CKA_SERIAL_NUMBER, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
1299 CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_EMAIL_PROTECTION,
1300 CKA_TRUST_CODE_SIGNING, CKA_TRUST_STEP_UP_APPROVED
1301 };
1302 static const CK_ULONG trustAttrsCount =
1303 sizeof(trustAttrs)/sizeof(trustAttrs[0]);
1304
1305 static const CK_ATTRIBUTE_TYPE smimeAttrs[] = {
1306 CKA_SUBJECT, CKA_NETSCAPE_EMAIL, CKA_NETSCAPE_SMIME_TIMESTAMP, CKA_VALUE
1307 };
1308 static const CK_ULONG smimeAttrsCount =
1309 sizeof(smimeAttrs)/sizeof(smimeAttrs[0]);
1310
1311 static const CK_ATTRIBUTE_TYPE crlAttrs[] = {
1312 CKA_SUBJECT, CKA_VALUE, CKA_NETSCAPE_URL, CKA_NETSCAPE_KRL
1313 };
1314 static const CK_ULONG crlAttrsCount =
1315 sizeof(crlAttrs)/sizeof(crlAttrs[0]);
1316
1317 /* copy an object based on it's table */
1318 CK_RV
1319 stfk_CopyTokenAttributes(SFTKObject *destObject,SFTKTokenObject *src_to,
1320 const CK_ATTRIBUTE_TYPE *attrArray, CK_ULONG attrCount)
1321 {
1322 SFTKAttribute *attribute;
1323 SFTKAttribute *newAttribute;
1324 CK_RV crv = CKR_OK;
1325 unsigned int i;
1326
1327 for (i=0; i < attrCount; i++) {
1328 if (!sftk_hasAttribute(destObject,attrArray[i])) {
1329 attribute =sftk_FindAttribute(&src_to->obj, attrArray[i]);
1330 if (!attribute) {
1331 continue; /* return CKR_ATTRIBUTE_VALUE_INVALID; */
1332 }
1333 /* we need to copy the attribute since each attribute
1334 * only has one set of link list pointers */
1335 newAttribute = sftk_NewAttribute( destObject,
1336 sftk_attr_expand(&attribute->attrib));
1337 sftk_FreeAttribute(attribute); /* free the old attribute */
1338 if (!newAttribute) {
1339 return CKR_HOST_MEMORY;
1340 }
1341 sftk_AddAttribute(destObject,newAttribute);
1342 }
1343 }
1344 return crv;
1345 }
1346
1347 CK_RV
1348 stfk_CopyTokenPrivateKey(SFTKObject *destObject,SFTKTokenObject *src_to)
1349 {
1350 CK_RV crv;
1351 CK_KEY_TYPE key_type;
1352 SFTKAttribute *attribute;
1353
1354 /* copy the common attributes for all keys first */
1355 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
1356 commonKeyAttrsCount);
1357 if (crv != CKR_OK) {
1358 goto fail;
1359 }
1360 /* copy the common attributes for all private keys next */
1361 crv = stfk_CopyTokenAttributes(destObject, src_to, commonPrivKeyAttrs,
1362 commonPrivKeyAttrsCount);
1363 if (crv != CKR_OK) {
1364 goto fail;
1365 }
1366 attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE);
1367 PORT_Assert(attribute); /* if it wasn't here, ww should have failed
1368 * copying the common attributes */
1369 if (!attribute) {
1370 /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
1371 * the fact is, the only reason we couldn't get the attribute would
1372 * be a memory error or database error (an error in the 'device').
1373 * if we have a database error code, we could return it here */
1374 crv = CKR_DEVICE_ERROR;
1375 goto fail;
1376 }
1377 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
1378 sftk_FreeAttribute(attribute);
1379
1380 /* finally copy the attributes for various private key types */
1381 switch (key_type) {
1382 case CKK_RSA:
1383 crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPrivKeyAttrs,
1384 rsaPrivKeyAttrsCount);
1385 break;
1386 case CKK_DSA:
1387 crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPrivKeyAttrs,
1388 dsaPrivKeyAttrsCount);
1389 break;
1390 case CKK_DH:
1391 crv = stfk_CopyTokenAttributes(destObject, src_to, dhPrivKeyAttrs,
1392 dhPrivKeyAttrsCount);
1393 break;
1394 #ifndef NSS_DISABLE_ECC
1395 case CKK_EC:
1396 crv = stfk_CopyTokenAttributes(destObject, src_to, ecPrivKeyAttrs,
1397 ecPrivKeyAttrsCount);
1398 break;
1399 #endif
1400 default:
1401 crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
1402 * of token keys into our database. */
1403 }
1404 fail:
1405 return crv;
1406 }
1407
1408 CK_RV
1409 stfk_CopyTokenPublicKey(SFTKObject *destObject,SFTKTokenObject *src_to)
1410 {
1411 CK_RV crv;
1412 CK_KEY_TYPE key_type;
1413 SFTKAttribute *attribute;
1414
1415 /* copy the common attributes for all keys first */
1416 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
1417 commonKeyAttrsCount);
1418 if (crv != CKR_OK) {
1419 goto fail;
1420 }
1421
1422 /* copy the common attributes for all public keys next */
1423 crv = stfk_CopyTokenAttributes(destObject, src_to, commonPubKeyAttrs,
1424 commonPubKeyAttrsCount);
1425 if (crv != CKR_OK) {
1426 goto fail;
1427 }
1428 attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE);
1429 PORT_Assert(attribute); /* if it wasn't here, ww should have failed
1430 * copying the common attributes */
1431 if (!attribute) {
1432 /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
1433 * the fact is, the only reason we couldn't get the attribute would
1434 * be a memory error or database error (an error in the 'device').
1435 * if we have a database error code, we could return it here */
1436 crv = CKR_DEVICE_ERROR;
1437 goto fail;
1438 }
1439 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
1440 sftk_FreeAttribute(attribute);
1441
1442 /* finally copy the attributes for various public key types */
1443 switch (key_type) {
1444 case CKK_RSA:
1445 crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPubKeyAttrs,
1446 rsaPubKeyAttrsCount);
1447 break;
1448 case CKK_DSA:
1449 crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPubKeyAttrs,
1450 dsaPubKeyAttrsCount);
1451 break;
1452 case CKK_DH:
1453 crv = stfk_CopyTokenAttributes(destObject, src_to, dhPubKeyAttrs,
1454 dhPubKeyAttrsCount);
1455 break;
1456 #ifndef NSS_DISABLE_ECC
1457 case CKK_EC:
1458 crv = stfk_CopyTokenAttributes(destObject, src_to, ecPubKeyAttrs,
1459 ecPubKeyAttrsCount);
1460 break;
1461 #endif
1462 default:
1463 crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
1464 * of token keys into our database. */
1465 }
1466 fail:
1467 return crv;
1468 }
1469 CK_RV
1470 stfk_CopyTokenSecretKey(SFTKObject *destObject,SFTKTokenObject *src_to)
1471 {
1472 CK_RV crv;
1473 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
1474 commonKeyAttrsCount);
1475 if (crv != CKR_OK) {
1476 goto fail;
1477 }
1478 crv = stfk_CopyTokenAttributes(destObject, src_to, secretKeyAttrs,
1479 secretKeyAttrsCount);
1480 fail:
1481 return crv;
1482 }
1483
1484 /*
1485 * Copy a token object. We need to explicitly copy the relevant
1486 * attributes since token objects don't store those attributes in
1487 * the token itself.
1488 */
1489 CK_RV
1490 sftk_CopyTokenObject(SFTKObject *destObject,SFTKObject *srcObject)
1491 {
1492 SFTKTokenObject *src_to = sftk_narrowToTokenObject(srcObject);
1493 CK_RV crv;
1494
1495 PORT_Assert(src_to);
1496 if (src_to == NULL) {
1497 return CKR_DEVICE_ERROR; /* internal state inconsistant */
1498 }
1499
1500 crv = stfk_CopyTokenAttributes(destObject, src_to, commonAttrs,
1501 commonAttrsCount);
1502 if (crv != CKR_OK) {
1503 goto fail;
1504 }
1505 switch (src_to->obj.objclass) {
1506 case CKO_CERTIFICATE:
1507 crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs,
1508 certAttrsCount);
1509 break;
1510 case CKO_NETSCAPE_TRUST:
1511 crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs,
1512 trustAttrsCount);
1513 break;
1514 case CKO_NETSCAPE_SMIME:
1515 crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs,
1516 smimeAttrsCount);
1517 break;
1518 case CKO_NETSCAPE_CRL:
1519 crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs,
1520 crlAttrsCount);
1521 break;
1522 case CKO_PRIVATE_KEY:
1523 crv = stfk_CopyTokenPrivateKey(destObject,src_to);
1524 break;
1525 case CKO_PUBLIC_KEY:
1526 crv = stfk_CopyTokenPublicKey(destObject,src_to);
1527 break;
1528 case CKO_SECRET_KEY:
1529 crv = stfk_CopyTokenSecretKey(destObject,src_to);
1530 break;
1531 default:
1532 crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
1533 * of token keys into our database. */
1534 }
1535 fail:
1536 return crv;
1537 }
1538
1539 /*
1540 * copy the attributes from one object to another. Don't overwrite existing
1541 * attributes. NOTE: This is a pretty expensive operation since it
1542 * grabs the attribute locks for the src object for a *long* time.
1543 */
1544 CK_RV
1545 sftk_CopyObject(SFTKObject *destObject,SFTKObject *srcObject)
1546 {
1547 SFTKAttribute *attribute;
1548 SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject);
1549 unsigned int i;
1550
1551 if (src_so == NULL) {
1552 return sftk_CopyTokenObject(destObject,srcObject);
1553 }
1554
1555 PZ_Lock(src_so->attributeLock);
1556 for(i=0; i < src_so->hashSize; i++) {
1557 attribute = src_so->head[i];
1558 do {
1559 if (attribute) {
1560 if (!sftk_hasAttribute(destObject,attribute->handle)) {
1561 /* we need to copy the attribute since each attribute
1562 * only has one set of link list pointers */
1563 SFTKAttribute *newAttribute = sftk_NewAttribute(
1564 destObject,sftk_attr_expand(&attribute->attrib));
1565 if (newAttribute == NULL) {
1566 PZ_Unlock(src_so->attributeLock);
1567 return CKR_HOST_MEMORY;
1568 }
1569 sftk_AddAttribute(destObject,newAttribute);
1570 }
1571 attribute=attribute->next;
1572 }
1573 } while (attribute != NULL);
1574 }
1575 PZ_Unlock(src_so->attributeLock);
1576
1577 return CKR_OK;
1578 }
1579
1580 /*
1581 * ******************** Search Utilities *******************************
1582 */
1583
1584 /* add an object to a search list */
1585 CK_RV
1586 AddToList(SFTKObjectListElement **list,SFTKObject *object)
1587 {
1588 SFTKObjectListElement *newElem =
1589 (SFTKObjectListElement *)PORT_Alloc(sizeof(SFTKObjectListElement));
1590
1591 if (newElem == NULL) return CKR_HOST_MEMORY;
1592
1593 newElem->next = *list;
1594 newElem->object = object;
1595 sftk_ReferenceObject(object);
1596
1597 *list = newElem;
1598 return CKR_OK;
1599 }
1600
1601
1602 /* return true if the object matches the template */
1603 PRBool
1604 sftk_objectMatch(SFTKObject *object,CK_ATTRIBUTE_PTR theTemplate,int count)
1605 {
1606 int i;
1607
1608 for (i=0; i < count; i++) {
1609 SFTKAttribute *attribute = sftk_FindAttribute(object,theTemplate[i].type );
1610 if (attribute == NULL) {
1611 return PR_FALSE;
1612 }
1613 if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) {
1614 if (PORT_Memcmp(attribute->attrib.pValue,theTemplate[i].pValue,
1615 theTemplate[i].ulValueLen) == 0) {
1616 sftk_FreeAttribute(attribute);
1617 continue;
1618 }
1619 }
1620 sftk_FreeAttribute(attribute);
1621 return PR_FALSE;
1622 }
1623 return PR_TRUE;
1624 }
1625
1626 /* search through all the objects in the queue and return the template matches
1627 * in the object list.
1628 */
1629 CK_RV
1630 sftk_searchObjectList(SFTKSearchResults *search,SFTKObject **head,
1631 unsigned int size, PZLock *lock, CK_ATTRIBUTE_PTR theTemplate,
1632 int count, PRBool isLoggedIn)
1633 {
1634 unsigned int i;
1635 SFTKObject *object;
1636 CK_RV crv = CKR_OK;
1637
1638 for(i=0; i < size; i++) {
1639 /* We need to hold the lock to copy a consistant version of
1640 * the linked list. */
1641 PZ_Lock(lock);
1642 for (object = head[i]; object != NULL; object= object->next) {
1643 if (sftk_objectMatch(object,theTemplate,count)) {
1644 /* don't return objects that aren't yet visible */
1645 if ((!isLoggedIn) && sftk_isTrue(object,CKA_PRIVATE)) continue;
1646 sftk_addHandle(search,object->handle);
1647 }
1648 }
1649 PZ_Unlock(lock);
1650 }
1651 return crv;
1652 }
1653
1654 /*
1655 * free a single list element. Return the Next object in the list.
1656 */
1657 SFTKObjectListElement *
1658 sftk_FreeObjectListElement(SFTKObjectListElement *objectList)
1659 {
1660 SFTKObjectListElement *ol = objectList->next;
1661
1662 sftk_FreeObject(objectList->object);
1663 PORT_Free(objectList);
1664 return ol;
1665 }
1666
1667 /* free an entire object list */
1668 void
1669 sftk_FreeObjectList(SFTKObjectListElement *objectList)
1670 {
1671 SFTKObjectListElement *ol;
1672
1673 for (ol= objectList; ol != NULL; ol = sftk_FreeObjectListElement(ol)) {}
1674 }
1675
1676 /*
1677 * free a search structure
1678 */
1679 void
1680 sftk_FreeSearch(SFTKSearchResults *search)
1681 {
1682 if (search->handles) {
1683 PORT_Free(search->handles);
1684 }
1685 PORT_Free(search);
1686 }
1687
1688 /*
1689 * ******************** Session Utilities *******************************
1690 */
1691
1692 /* update the sessions state based in it's flags and wether or not it's
1693 * logged in */
1694 void
1695 sftk_update_state(SFTKSlot *slot,SFTKSession *session)
1696 {
1697 if (slot->isLoggedIn) {
1698 if (slot->ssoLoggedIn) {
1699 session->info.state = CKS_RW_SO_FUNCTIONS;
1700 } else if (session->info.flags & CKF_RW_SESSION) {
1701 session->info.state = CKS_RW_USER_FUNCTIONS;
1702 } else {
1703 session->info.state = CKS_RO_USER_FUNCTIONS;
1704 }
1705 } else {
1706 if (session->info.flags & CKF_RW_SESSION) {
1707 session->info.state = CKS_RW_PUBLIC_SESSION;
1708 } else {
1709 session->info.state = CKS_RO_PUBLIC_SESSION;
1710 }
1711 }
1712 }
1713
1714 /* update the state of all the sessions on a slot */
1715 void
1716 sftk_update_all_states(SFTKSlot *slot)
1717 {
1718 unsigned int i;
1719 SFTKSession *session;
1720
1721 for (i=0; i < slot->sessHashSize; i++) {
1722 PZLock *lock = SFTK_SESSION_LOCK(slot,i);
1723 PZ_Lock(lock);
1724 for (session = slot->head[i]; session; session = session->next) {
1725 sftk_update_state(slot,session);
1726 }
1727 PZ_Unlock(lock);
1728 }
1729 }
1730
1731 /*
1732 * context are cipher and digest contexts that are associated with a session
1733 */
1734 void
1735 sftk_FreeContext(SFTKSessionContext *context)
1736 {
1737 if (context->cipherInfo) {
1738 (*context->destroy)(context->cipherInfo,PR_TRUE);
1739 }
1740 if (context->hashInfo) {
1741 (*context->hashdestroy)(context->hashInfo,PR_TRUE);
1742 }
1743 if (context->key) {
1744 sftk_FreeObject(context->key);
1745 context->key = NULL;
1746 }
1747 PORT_Free(context);
1748 }
1749
1750 /*
1751 * create a new nession. NOTE: The session handle is not set, and the
1752 * session is not added to the slot's session queue.
1753 */
1754 SFTKSession *
1755 sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
1756 CK_FLAGS flags)
1757 {
1758 SFTKSession *session;
1759 SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
1760
1761 if (slot == NULL) return NULL;
1762
1763 session = (SFTKSession*)PORT_Alloc(sizeof(SFTKSession));
1764 if (session == NULL) return NULL;
1765
1766 session->next = session->prev = NULL;
1767 session->refCount = 1;
1768 session->enc_context = NULL;
1769 session->hash_context = NULL;
1770 session->sign_context = NULL;
1771 session->search = NULL;
1772 session->objectIDCount = 1;
1773 session->objectLock = PZ_NewLock(nssILockObject);
1774 if (session->objectLock == NULL) {
1775 PORT_Free(session);
1776 return NULL;
1777 }
1778 session->objects[0] = NULL;
1779
1780 session->slot = slot;
1781 session->notify = notify;
1782 session->appData = pApplication;
1783 session->info.flags = flags;
1784 session->info.slotID = slotID;
1785 session->info.ulDeviceError = 0;
1786 sftk_update_state(slot,session);
1787 return session;
1788 }
1789
1790
1791 /* free all the data associated with a session. */
1792 static void
1793 sftk_DestroySession(SFTKSession *session)
1794 {
1795 SFTKObjectList *op,*next;
1796 PORT_Assert(session->refCount == 0);
1797
1798 /* clean out the attributes */
1799 /* since no one is referencing us, it's safe to walk the chain
1800 * without a lock */
1801 for (op = session->objects[0]; op != NULL; op = next) {
1802 next = op->next;
1803 /* paranoia */
1804 op->next = op->prev = NULL;
1805 sftk_DeleteObject(session,op->parent);
1806 }
1807 PZ_DestroyLock(session->objectLock);
1808 if (session->enc_context) {
1809 sftk_FreeContext(session->enc_context);
1810 }
1811 if (session->hash_context) {
1812 sftk_FreeContext(session->hash_context);
1813 }
1814 if (session->sign_context) {
1815 sftk_FreeContext(session->sign_context);
1816 }
1817 if (session->search) {
1818 sftk_FreeSearch(session->search);
1819 }
1820 PORT_Free(session);
1821 }
1822
1823
1824 /*
1825 * look up a session structure from a session handle
1826 * generate a reference to it.
1827 */
1828 SFTKSession *
1829 sftk_SessionFromHandle(CK_SESSION_HANDLE handle)
1830 {
1831 SFTKSlot *slot = sftk_SlotFromSessionHandle(handle);
1832 SFTKSession *session;
1833 PZLock *lock;
1834
1835 if (!slot) return NULL;
1836 lock = SFTK_SESSION_LOCK(slot,handle);
1837
1838 PZ_Lock(lock);
1839 sftkqueue_find(session,handle,slot->head,slot->sessHashSize);
1840 if (session) session->refCount++;
1841 PZ_Unlock(lock);
1842
1843 return (session);
1844 }
1845
1846 /*
1847 * release a reference to a session handle
1848 */
1849 void
1850 sftk_FreeSession(SFTKSession *session)
1851 {
1852 PRBool destroy = PR_FALSE;
1853 SFTKSlot *slot = sftk_SlotFromSession(session);
1854 PZLock *lock = SFTK_SESSION_LOCK(slot,session->handle);
1855
1856 PZ_Lock(lock);
1857 if (session->refCount == 1) destroy = PR_TRUE;
1858 session->refCount--;
1859 PZ_Unlock(lock);
1860
1861 if (destroy) sftk_DestroySession(session);
1862 }
1863
1864 void
1865 sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle)
1866 {
1867 if (search->handles == NULL) {
1868 return;
1869 }
1870 if (search->size >= search->array_size) {
1871 search->array_size += NSC_SEARCH_BLOCK_SIZE;
1872 search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles,
1873 sizeof(CK_OBJECT_HANDLE)* search->array_size);
1874 if (search->handles == NULL) {
1875 return;
1876 }
1877 }
1878 search->handles[search->size] = handle;
1879 search->size++;
1880 }
1881
1882 static CK_RV
1883 handleToClass(SFTKSlot *slot, CK_OBJECT_HANDLE handle,
1884 CK_OBJECT_CLASS *objClass)
1885 {
1886 SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, handle);
1887 CK_ATTRIBUTE objClassTemplate;
1888 CK_RV crv;
1889
1890 *objClass = CKO_DATA;
1891 objClassTemplate.type = CKA_CLASS;
1892 objClassTemplate.pValue = objClass;
1893 objClassTemplate.ulValueLen = sizeof(*objClass);
1894 crv = sftkdb_GetAttributeValue(dbHandle, handle, &objClassTemplate, 1);
1895 sftk_freeDB(dbHandle);
1896 return crv;
1897 }
1898
1899 SFTKObject *
1900 sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
1901 {
1902 SFTKObject *object = NULL;
1903 PRBool hasLocks = PR_FALSE;
1904 CK_RV crv;
1905
1906 object = sftk_GetObjectFromList(&hasLocks, PR_FALSE, &tokenObjectList, 0,
1907 PR_FALSE);
1908 if (object == NULL) {
1909 return NULL;
1910 }
1911
1912 object->handle = handle;
1913 /* every object must have a class, if we can't get it, the object
1914 * doesn't exist */
1915 crv = handleToClass(slot, handle, &object->objclass);
1916 if (crv != CKR_OK) {
1917 goto loser;
1918 }
1919 object->slot = slot;
1920 object->objectInfo = NULL;
1921 object->infoFree = NULL;
1922 if (!hasLocks) {
1923 object->refLock = PZ_NewLock(nssILockRefLock);
1924 }
1925 if (object->refLock == NULL) {
1926 goto loser;
1927 }
1928 object->refCount = 1;
1929
1930 return object;
1931 loser:
1932 if (object) {
1933 (void) sftk_DestroyObject(object);
1934 }
1935 return NULL;
1936
1937 }
1938
1939 SFTKTokenObject *
1940 sftk_convertSessionToToken(SFTKObject *obj)
1941 {
1942 SECItem *key;
1943 SFTKSessionObject *so = (SFTKSessionObject *)obj;
1944 SFTKTokenObject *to = sftk_narrowToTokenObject(obj);
1945 SECStatus rv;
1946
1947 sftk_DestroySessionObjectData(so);
1948 PZ_DestroyLock(so->attributeLock);
1949 if (to == NULL) {
1950 return NULL;
1951 }
1952 sftk_tokenKeyLock(so->obj.slot);
1953 key = sftk_lookupTokenKeyByHandle(so->obj.slot,so->obj.handle);
1954 if (key == NULL) {
1955 sftk_tokenKeyUnlock(so->obj.slot);
1956 return NULL;
1957 }
1958 rv = SECITEM_CopyItem(NULL,&to->dbKey,key);
1959 sftk_tokenKeyUnlock(so->obj.slot);
1960 if (rv == SECFailure) {
1961 return NULL;
1962 }
1963
1964 return to;
1965 }
1966
1967 SFTKSessionObject *
1968 sftk_narrowToSessionObject(SFTKObject *obj)
1969 {
1970 return !sftk_isToken(obj->handle) ? (SFTKSessionObject *)obj : NULL;
1971 }
1972
1973 SFTKTokenObject *
1974 sftk_narrowToTokenObject(SFTKObject *obj)
1975 {
1976 return sftk_isToken(obj->handle) ? (SFTKTokenObject *)obj : NULL;
1977 }
1978
OLDNEW
« no previous file with comments | « nss/lib/softoken/pkcs11ni.h ('k') | nss/lib/softoken/sdb.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698