Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/softoken/pkcs11u.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 /* | |
5 * 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_KEY)); | |
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 SFTKTokenObject *to = sftk_narrowToTokenObject(object); | |
1178 CK_RV crv = CKR_OK; | |
1179 PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize); | |
1180 | |
1181 /* Handle Token case */ | |
1182 if (so && so->session) { | |
1183 SFTKSession *session = so->session; | |
1184 PZ_Lock(session->objectLock); | |
1185 sftkqueue_delete(&so->sessionList,0,session->objects,0); | |
1186 PZ_Unlock(session->objectLock); | |
1187 PZ_Lock(slot->objectLock); | |
1188 sftkqueue_delete2(object, object->handle, index, slot->sessObjHashTable); | |
1189 PZ_Unlock(slot->objectLock); | |
1190 sftkqueue_clear_deleted_element(object); | |
1191 sftk_FreeObject(object); /* free the reference owned by the queue */ | |
1192 } else { | |
1193 SFTKDBHandle *handle = sftk_getDBForTokenObject(slot, object->handle); | |
1194 | |
1195 PORT_Assert(to); | |
1196 crv = sftkdb_DestroyObject(handle, object->handle); | |
1197 sftk_freeDB(handle); | |
1198 } | |
1199 return crv; | |
1200 } | |
1201 | |
1202 /* | |
1203 * Token objects don't explicitly store their attributes, so we need to know | |
1204 * what attributes make up a particular token object before we can copy it. | |
1205 * below are the tables by object type. | |
1206 */ | |
1207 static const CK_ATTRIBUTE_TYPE commonAttrs[] = { | |
1208 CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_MODIFIABLE | |
1209 }; | |
1210 static const CK_ULONG commonAttrsCount = | |
1211 sizeof(commonAttrs)/sizeof(commonAttrs[0]); | |
1212 | |
1213 static const CK_ATTRIBUTE_TYPE commonKeyAttrs[] = { | |
1214 CKA_ID, CKA_START_DATE, CKA_END_DATE, CKA_DERIVE, CKA_LOCAL, CKA_KEY_TYPE | |
1215 }; | |
1216 static const CK_ULONG commonKeyAttrsCount = | |
1217 sizeof(commonKeyAttrs)/sizeof(commonKeyAttrs[0]); | |
1218 | |
1219 static const CK_ATTRIBUTE_TYPE secretKeyAttrs[] = { | |
1220 CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN, | |
1221 CKA_VERIFY, CKA_WRAP, CKA_UNWRAP, CKA_VALUE | |
1222 }; | |
1223 static const CK_ULONG secretKeyAttrsCount = | |
1224 sizeof(secretKeyAttrs)/sizeof(secretKeyAttrs[0]); | |
1225 | |
1226 static const CK_ATTRIBUTE_TYPE commonPubKeyAttrs[] = { | |
1227 CKA_ENCRYPT, CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_WRAP, CKA_SUBJECT | |
1228 }; | |
1229 static const CK_ULONG commonPubKeyAttrsCount = | |
1230 sizeof(commonPubKeyAttrs)/sizeof(commonPubKeyAttrs[0]); | |
1231 | |
1232 static const CK_ATTRIBUTE_TYPE rsaPubKeyAttrs[] = { | |
1233 CKA_MODULUS, CKA_PUBLIC_EXPONENT | |
1234 }; | |
1235 static const CK_ULONG rsaPubKeyAttrsCount = | |
1236 sizeof(rsaPubKeyAttrs)/sizeof(rsaPubKeyAttrs[0]); | |
1237 | |
1238 static const CK_ATTRIBUTE_TYPE dsaPubKeyAttrs[] = { | |
1239 CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE | |
1240 }; | |
1241 static const CK_ULONG dsaPubKeyAttrsCount = | |
1242 sizeof(dsaPubKeyAttrs)/sizeof(dsaPubKeyAttrs[0]); | |
1243 | |
1244 static const CK_ATTRIBUTE_TYPE dhPubKeyAttrs[] = { | |
1245 CKA_PRIME, CKA_BASE, CKA_VALUE | |
1246 }; | |
1247 static const CK_ULONG dhPubKeyAttrsCount = | |
1248 sizeof(dhPubKeyAttrs)/sizeof(dhPubKeyAttrs[0]); | |
1249 #ifndef NSS_DISABLE_ECC | |
1250 static const CK_ATTRIBUTE_TYPE ecPubKeyAttrs[] = { | |
1251 CKA_EC_PARAMS, CKA_EC_POINT | |
1252 }; | |
1253 static const CK_ULONG ecPubKeyAttrsCount = | |
1254 sizeof(ecPubKeyAttrs)/sizeof(ecPubKeyAttrs[0]); | |
1255 #endif | |
1256 | |
1257 static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = { | |
1258 CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_UNWRAP, CKA_SUBJECT, | |
1259 CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB | |
1260 }; | |
1261 static const CK_ULONG commonPrivKeyAttrsCount = | |
1262 sizeof(commonPrivKeyAttrs)/sizeof(commonPrivKeyAttrs[0]); | |
1263 | |
1264 static const CK_ATTRIBUTE_TYPE rsaPrivKeyAttrs[] = { | |
1265 CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, | |
1266 CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT | |
1267 }; | |
1268 static const CK_ULONG rsaPrivKeyAttrsCount = | |
1269 sizeof(rsaPrivKeyAttrs)/sizeof(rsaPrivKeyAttrs[0]); | |
1270 | |
1271 static const CK_ATTRIBUTE_TYPE dsaPrivKeyAttrs[] = { | |
1272 CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE | |
1273 }; | |
1274 static const CK_ULONG dsaPrivKeyAttrsCount = | |
1275 sizeof(dsaPrivKeyAttrs)/sizeof(dsaPrivKeyAttrs[0]); | |
1276 | |
1277 static const CK_ATTRIBUTE_TYPE dhPrivKeyAttrs[] = { | |
1278 CKA_PRIME, CKA_BASE, CKA_VALUE | |
1279 }; | |
1280 static const CK_ULONG dhPrivKeyAttrsCount = | |
1281 sizeof(dhPrivKeyAttrs)/sizeof(dhPrivKeyAttrs[0]); | |
1282 #ifndef NSS_DISABLE_ECC | |
1283 static const CK_ATTRIBUTE_TYPE ecPrivKeyAttrs[] = { | |
1284 CKA_EC_PARAMS, CKA_VALUE | |
1285 }; | |
1286 static const CK_ULONG ecPrivKeyAttrsCount = | |
1287 sizeof(ecPrivKeyAttrs)/sizeof(ecPrivKeyAttrs[0]); | |
1288 #endif | |
1289 | |
1290 static const CK_ATTRIBUTE_TYPE certAttrs[] = { | |
1291 CKA_CERTIFICATE_TYPE, CKA_VALUE, CKA_SUBJECT, CKA_ISSUER, CKA_SERIAL_NUMBER | |
1292 }; | |
1293 static const CK_ULONG certAttrsCount = | |
1294 sizeof(certAttrs)/sizeof(certAttrs[0]); | |
1295 | |
1296 static const CK_ATTRIBUTE_TYPE trustAttrs[] = { | |
1297 CKA_ISSUER, CKA_SERIAL_NUMBER, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH, | |
1298 CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_EMAIL_PROTECTION, | |
1299 CKA_TRUST_CODE_SIGNING, CKA_TRUST_STEP_UP_APPROVED | |
1300 }; | |
1301 static const CK_ULONG trustAttrsCount = | |
1302 sizeof(trustAttrs)/sizeof(trustAttrs[0]); | |
1303 | |
1304 static const CK_ATTRIBUTE_TYPE smimeAttrs[] = { | |
1305 CKA_SUBJECT, CKA_NETSCAPE_EMAIL, CKA_NETSCAPE_SMIME_TIMESTAMP, CKA_VALUE | |
1306 }; | |
1307 static const CK_ULONG smimeAttrsCount = | |
1308 sizeof(smimeAttrs)/sizeof(smimeAttrs[0]); | |
1309 | |
1310 static const CK_ATTRIBUTE_TYPE crlAttrs[] = { | |
1311 CKA_SUBJECT, CKA_VALUE, CKA_NETSCAPE_URL, CKA_NETSCAPE_KRL | |
1312 }; | |
1313 static const CK_ULONG crlAttrsCount = | |
1314 sizeof(crlAttrs)/sizeof(crlAttrs[0]); | |
1315 | |
1316 /* copy an object based on it's table */ | |
1317 CK_RV | |
1318 stfk_CopyTokenAttributes(SFTKObject *destObject,SFTKTokenObject *src_to, | |
1319 const CK_ATTRIBUTE_TYPE *attrArray, CK_ULONG attrCount) | |
1320 { | |
1321 SFTKAttribute *attribute; | |
1322 SFTKAttribute *newAttribute; | |
1323 CK_RV crv = CKR_OK; | |
1324 unsigned int i; | |
1325 | |
1326 for (i=0; i < attrCount; i++) { | |
1327 if (!sftk_hasAttribute(destObject,attrArray[i])) { | |
1328 attribute =sftk_FindAttribute(&src_to->obj, attrArray[i]); | |
1329 if (!attribute) { | |
1330 continue; /* return CKR_ATTRIBUTE_VALUE_INVALID; */ | |
1331 } | |
1332 /* we need to copy the attribute since each attribute | |
1333 * only has one set of link list pointers */ | |
1334 newAttribute = sftk_NewAttribute( destObject, | |
1335 sftk_attr_expand(&attribute->attrib)); | |
1336 sftk_FreeAttribute(attribute); /* free the old attribute */ | |
1337 if (!newAttribute) { | |
1338 return CKR_HOST_MEMORY; | |
1339 } | |
1340 sftk_AddAttribute(destObject,newAttribute); | |
1341 } | |
1342 } | |
1343 return crv; | |
1344 } | |
1345 | |
1346 CK_RV | |
1347 stfk_CopyTokenPrivateKey(SFTKObject *destObject,SFTKTokenObject *src_to) | |
1348 { | |
1349 CK_RV crv; | |
1350 CK_KEY_TYPE key_type; | |
1351 SFTKAttribute *attribute; | |
1352 | |
1353 /* copy the common attributes for all keys first */ | |
1354 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, | |
1355 commonKeyAttrsCount); | |
1356 if (crv != CKR_OK) { | |
1357 goto fail; | |
1358 } | |
1359 /* copy the common attributes for all private keys next */ | |
1360 crv = stfk_CopyTokenAttributes(destObject, src_to, commonPrivKeyAttrs, | |
1361 commonPrivKeyAttrsCount); | |
1362 if (crv != CKR_OK) { | |
1363 goto fail; | |
1364 } | |
1365 attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE); | |
1366 PORT_Assert(attribute); /* if it wasn't here, ww should have failed | |
1367 * copying the common attributes */ | |
1368 if (!attribute) { | |
1369 /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but | |
1370 * the fact is, the only reason we couldn't get the attribute would | |
1371 * be a memory error or database error (an error in the 'device'). | |
1372 * if we have a database error code, we could return it here */ | |
1373 crv = CKR_DEVICE_ERROR; | |
1374 goto fail; | |
1375 } | |
1376 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; | |
1377 sftk_FreeAttribute(attribute); | |
1378 | |
1379 /* finally copy the attributes for various private key types */ | |
1380 switch (key_type) { | |
1381 case CKK_RSA: | |
1382 crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPrivKeyAttrs, | |
1383 rsaPrivKeyAttrsCount); | |
1384 break; | |
1385 case CKK_DSA: | |
1386 crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPrivKeyAttrs, | |
1387 dsaPrivKeyAttrsCount); | |
1388 break; | |
1389 case CKK_DH: | |
1390 crv = stfk_CopyTokenAttributes(destObject, src_to, dhPrivKeyAttrs, | |
1391 dhPrivKeyAttrsCount); | |
1392 break; | |
1393 #ifndef NSS_DISABLE_ECC | |
1394 case CKK_EC: | |
1395 crv = stfk_CopyTokenAttributes(destObject, src_to, ecPrivKeyAttrs, | |
1396 ecPrivKeyAttrsCount); | |
1397 break; | |
1398 #endif | |
1399 default: | |
1400 crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types | |
1401 * of token keys into our database. */ | |
1402 } | |
1403 fail: | |
1404 return crv; | |
1405 } | |
1406 | |
1407 CK_RV | |
1408 stfk_CopyTokenPublicKey(SFTKObject *destObject,SFTKTokenObject *src_to) | |
1409 { | |
1410 CK_RV crv; | |
1411 CK_KEY_TYPE key_type; | |
1412 SFTKAttribute *attribute; | |
1413 | |
1414 /* copy the common attributes for all keys first */ | |
1415 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, | |
1416 commonKeyAttrsCount); | |
1417 if (crv != CKR_OK) { | |
1418 goto fail; | |
1419 } | |
1420 | |
1421 /* copy the common attributes for all public keys next */ | |
1422 crv = stfk_CopyTokenAttributes(destObject, src_to, commonPubKeyAttrs, | |
1423 commonPubKeyAttrsCount); | |
1424 if (crv != CKR_OK) { | |
1425 goto fail; | |
1426 } | |
1427 attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE); | |
1428 PORT_Assert(attribute); /* if it wasn't here, ww should have failed | |
1429 * copying the common attributes */ | |
1430 if (!attribute) { | |
1431 /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but | |
1432 * the fact is, the only reason we couldn't get the attribute would | |
1433 * be a memory error or database error (an error in the 'device'). | |
1434 * if we have a database error code, we could return it here */ | |
1435 crv = CKR_DEVICE_ERROR; | |
1436 goto fail; | |
1437 } | |
1438 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; | |
1439 sftk_FreeAttribute(attribute); | |
1440 | |
1441 /* finally copy the attributes for various public key types */ | |
1442 switch (key_type) { | |
1443 case CKK_RSA: | |
1444 crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPubKeyAttrs, | |
1445 rsaPubKeyAttrsCount); | |
1446 break; | |
1447 case CKK_DSA: | |
1448 crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPubKeyAttrs, | |
1449 dsaPubKeyAttrsCount); | |
1450 break; | |
1451 case CKK_DH: | |
1452 crv = stfk_CopyTokenAttributes(destObject, src_to, dhPubKeyAttrs, | |
1453 dhPubKeyAttrsCount); | |
1454 break; | |
1455 #ifndef NSS_DISABLE_ECC | |
1456 case CKK_EC: | |
1457 crv = stfk_CopyTokenAttributes(destObject, src_to, ecPubKeyAttrs, | |
1458 ecPubKeyAttrsCount); | |
1459 break; | |
1460 #endif | |
1461 default: | |
1462 crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types | |
1463 * of token keys into our database. */ | |
1464 } | |
1465 fail: | |
1466 return crv; | |
1467 } | |
1468 CK_RV | |
1469 stfk_CopyTokenSecretKey(SFTKObject *destObject,SFTKTokenObject *src_to) | |
1470 { | |
1471 CK_RV crv; | |
1472 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, | |
1473 commonKeyAttrsCount); | |
1474 if (crv != CKR_OK) { | |
1475 goto fail; | |
1476 } | |
1477 crv = stfk_CopyTokenAttributes(destObject, src_to, secretKeyAttrs, | |
1478 secretKeyAttrsCount); | |
1479 fail: | |
1480 return crv; | |
1481 } | |
1482 | |
1483 /* | |
1484 * Copy a token object. We need to explicitly copy the relevant | |
1485 * attributes since token objects don't store those attributes in | |
1486 * the token itself. | |
1487 */ | |
1488 CK_RV | |
1489 sftk_CopyTokenObject(SFTKObject *destObject,SFTKObject *srcObject) | |
1490 { | |
1491 SFTKTokenObject *src_to = sftk_narrowToTokenObject(srcObject); | |
1492 CK_RV crv; | |
1493 | |
1494 PORT_Assert(src_to); | |
1495 if (src_to == NULL) { | |
1496 return CKR_DEVICE_ERROR; /* internal state inconsistant */ | |
1497 } | |
1498 | |
1499 crv = stfk_CopyTokenAttributes(destObject, src_to, commonAttrs, | |
1500 commonAttrsCount); | |
1501 if (crv != CKR_OK) { | |
1502 goto fail; | |
1503 } | |
1504 switch (src_to->obj.objclass) { | |
1505 case CKO_CERTIFICATE: | |
1506 crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs, | |
1507 certAttrsCount); | |
1508 break; | |
1509 case CKO_NETSCAPE_TRUST: | |
1510 crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs, | |
1511 trustAttrsCount); | |
1512 break; | |
1513 case CKO_NETSCAPE_SMIME: | |
1514 crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs, | |
1515 smimeAttrsCount); | |
1516 break; | |
1517 case CKO_NETSCAPE_CRL: | |
1518 crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs, | |
1519 crlAttrsCount); | |
1520 break; | |
1521 case CKO_PRIVATE_KEY: | |
1522 crv = stfk_CopyTokenPrivateKey(destObject,src_to); | |
1523 break; | |
1524 case CKO_PUBLIC_KEY: | |
1525 crv = stfk_CopyTokenPublicKey(destObject,src_to); | |
1526 break; | |
1527 case CKO_SECRET_KEY: | |
1528 crv = stfk_CopyTokenSecretKey(destObject,src_to); | |
1529 break; | |
1530 default: | |
1531 crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types | |
1532 * of token keys into our database. */ | |
1533 } | |
1534 fail: | |
1535 return crv; | |
1536 } | |
1537 | |
1538 /* | |
1539 * copy the attributes from one object to another. Don't overwrite existing | |
1540 * attributes. NOTE: This is a pretty expensive operation since it | |
1541 * grabs the attribute locks for the src object for a *long* time. | |
1542 */ | |
1543 CK_RV | |
1544 sftk_CopyObject(SFTKObject *destObject,SFTKObject *srcObject) | |
1545 { | |
1546 SFTKAttribute *attribute; | |
1547 SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject); | |
1548 unsigned int i; | |
1549 | |
1550 if (src_so == NULL) { | |
1551 return sftk_CopyTokenObject(destObject,srcObject); | |
1552 } | |
1553 | |
1554 PZ_Lock(src_so->attributeLock); | |
1555 for(i=0; i < src_so->hashSize; i++) { | |
1556 attribute = src_so->head[i]; | |
1557 do { | |
1558 if (attribute) { | |
1559 if (!sftk_hasAttribute(destObject,attribute->handle)) { | |
1560 /* we need to copy the attribute since each attribute | |
1561 * only has one set of link list pointers */ | |
1562 SFTKAttribute *newAttribute = sftk_NewAttribute( | |
1563 destObject,sftk_attr_expand(&attribute->attrib)); | |
1564 if (newAttribute == NULL) { | |
1565 PZ_Unlock(src_so->attributeLock); | |
1566 return CKR_HOST_MEMORY; | |
1567 } | |
1568 sftk_AddAttribute(destObject,newAttribute); | |
1569 } | |
1570 attribute=attribute->next; | |
1571 } | |
1572 } while (attribute != NULL); | |
1573 } | |
1574 PZ_Unlock(src_so->attributeLock); | |
1575 | |
1576 return CKR_OK; | |
1577 } | |
1578 | |
1579 /* | |
1580 * ******************** Search Utilities ******************************* | |
1581 */ | |
1582 | |
1583 /* add an object to a search list */ | |
1584 CK_RV | |
1585 AddToList(SFTKObjectListElement **list,SFTKObject *object) | |
1586 { | |
1587 SFTKObjectListElement *newElem = | |
1588 (SFTKObjectListElement *)PORT_Alloc(sizeof(SFTKObjectListElement)); | |
1589 | |
1590 if (newElem == NULL) return CKR_HOST_MEMORY; | |
1591 | |
1592 newElem->next = *list; | |
1593 newElem->object = object; | |
1594 sftk_ReferenceObject(object); | |
1595 | |
1596 *list = newElem; | |
1597 return CKR_OK; | |
1598 } | |
1599 | |
1600 | |
1601 /* return true if the object matches the template */ | |
1602 PRBool | |
1603 sftk_objectMatch(SFTKObject *object,CK_ATTRIBUTE_PTR theTemplate,int count) | |
1604 { | |
1605 int i; | |
1606 | |
1607 for (i=0; i < count; i++) { | |
1608 SFTKAttribute *attribute = sftk_FindAttribute(object,theTemplate[i].type); | |
1609 if (attribute == NULL) { | |
1610 return PR_FALSE; | |
1611 } | |
1612 if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) { | |
1613 if (PORT_Memcmp(attribute->attrib.pValue,theTemplate[i].pValue, | |
1614 theTemplate[i].ulValueLen) == 0) { | |
1615 sftk_FreeAttribute(attribute); | |
1616 continue; | |
1617 } | |
1618 } | |
1619 sftk_FreeAttribute(attribute); | |
1620 return PR_FALSE; | |
1621 } | |
1622 return PR_TRUE; | |
1623 } | |
1624 | |
1625 /* search through all the objects in the queue and return the template matches | |
1626 * in the object list. | |
1627 */ | |
1628 CK_RV | |
1629 sftk_searchObjectList(SFTKSearchResults *search,SFTKObject **head, | |
1630 unsigned int size, PZLock *lock, CK_ATTRIBUTE_PTR theTemplate, | |
1631 int count, PRBool isLoggedIn) | |
1632 { | |
1633 unsigned int i; | |
1634 SFTKObject *object; | |
1635 CK_RV crv = CKR_OK; | |
1636 | |
1637 for(i=0; i < size; i++) { | |
1638 /* We need to hold the lock to copy a consistant version of | |
1639 * the linked list. */ | |
1640 PZ_Lock(lock); | |
1641 for (object = head[i]; object != NULL; object= object->next) { | |
1642 if (sftk_objectMatch(object,theTemplate,count)) { | |
1643 /* don't return objects that aren't yet visible */ | |
1644 if ((!isLoggedIn) && sftk_isTrue(object,CKA_PRIVATE)) continue; | |
1645 sftk_addHandle(search,object->handle); | |
1646 } | |
1647 } | |
1648 PZ_Unlock(lock); | |
1649 } | |
1650 return crv; | |
1651 } | |
1652 | |
1653 /* | |
1654 * free a single list element. Return the Next object in the list. | |
1655 */ | |
1656 SFTKObjectListElement * | |
1657 sftk_FreeObjectListElement(SFTKObjectListElement *objectList) | |
1658 { | |
1659 SFTKObjectListElement *ol = objectList->next; | |
1660 | |
1661 sftk_FreeObject(objectList->object); | |
1662 PORT_Free(objectList); | |
1663 return ol; | |
1664 } | |
1665 | |
1666 /* free an entire object list */ | |
1667 void | |
1668 sftk_FreeObjectList(SFTKObjectListElement *objectList) | |
1669 { | |
1670 SFTKObjectListElement *ol; | |
1671 | |
1672 for (ol= objectList; ol != NULL; ol = sftk_FreeObjectListElement(ol)) {} | |
1673 } | |
1674 | |
1675 /* | |
1676 * free a search structure | |
1677 */ | |
1678 void | |
1679 sftk_FreeSearch(SFTKSearchResults *search) | |
1680 { | |
1681 if (search->handles) { | |
1682 PORT_Free(search->handles); | |
1683 } | |
1684 PORT_Free(search); | |
1685 } | |
1686 | |
1687 /* | |
1688 * ******************** Session Utilities ******************************* | |
1689 */ | |
1690 | |
1691 /* update the sessions state based in it's flags and wether or not it's | |
1692 * logged in */ | |
1693 void | |
1694 sftk_update_state(SFTKSlot *slot,SFTKSession *session) | |
1695 { | |
1696 if (slot->isLoggedIn) { | |
1697 if (slot->ssoLoggedIn) { | |
1698 session->info.state = CKS_RW_SO_FUNCTIONS; | |
1699 } else if (session->info.flags & CKF_RW_SESSION) { | |
1700 session->info.state = CKS_RW_USER_FUNCTIONS; | |
1701 } else { | |
1702 session->info.state = CKS_RO_USER_FUNCTIONS; | |
1703 } | |
1704 } else { | |
1705 if (session->info.flags & CKF_RW_SESSION) { | |
1706 session->info.state = CKS_RW_PUBLIC_SESSION; | |
1707 } else { | |
1708 session->info.state = CKS_RO_PUBLIC_SESSION; | |
1709 } | |
1710 } | |
1711 } | |
1712 | |
1713 /* update the state of all the sessions on a slot */ | |
1714 void | |
1715 sftk_update_all_states(SFTKSlot *slot) | |
1716 { | |
1717 unsigned int i; | |
1718 SFTKSession *session; | |
1719 | |
1720 for (i=0; i < slot->sessHashSize; i++) { | |
1721 PZLock *lock = SFTK_SESSION_LOCK(slot,i); | |
1722 PZ_Lock(lock); | |
1723 for (session = slot->head[i]; session; session = session->next) { | |
1724 sftk_update_state(slot,session); | |
1725 } | |
1726 PZ_Unlock(lock); | |
1727 } | |
1728 } | |
1729 | |
1730 /* | |
1731 * context are cipher and digest contexts that are associated with a session | |
1732 */ | |
1733 void | |
1734 sftk_FreeContext(SFTKSessionContext *context) | |
1735 { | |
1736 if (context->cipherInfo) { | |
1737 (*context->destroy)(context->cipherInfo,PR_TRUE); | |
1738 } | |
1739 if (context->hashInfo) { | |
1740 (*context->hashdestroy)(context->hashInfo,PR_TRUE); | |
1741 } | |
1742 if (context->key) { | |
1743 sftk_FreeObject(context->key); | |
1744 context->key = NULL; | |
1745 } | |
1746 PORT_Free(context); | |
1747 } | |
1748 | |
1749 /* | |
1750 * create a new nession. NOTE: The session handle is not set, and the | |
1751 * session is not added to the slot's session queue. | |
1752 */ | |
1753 SFTKSession * | |
1754 sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication, | |
1755 CK_FLAGS flags) | |
1756 { | |
1757 SFTKSession *session; | |
1758 SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); | |
1759 | |
1760 if (slot == NULL) return NULL; | |
1761 | |
1762 session = (SFTKSession*)PORT_Alloc(sizeof(SFTKSession)); | |
1763 if (session == NULL) return NULL; | |
1764 | |
1765 session->next = session->prev = NULL; | |
1766 session->refCount = 1; | |
1767 session->enc_context = NULL; | |
1768 session->hash_context = NULL; | |
1769 session->sign_context = NULL; | |
1770 session->search = NULL; | |
1771 session->objectIDCount = 1; | |
1772 session->objectLock = PZ_NewLock(nssILockObject); | |
1773 if (session->objectLock == NULL) { | |
1774 PORT_Free(session); | |
1775 return NULL; | |
1776 } | |
1777 session->objects[0] = NULL; | |
1778 | |
1779 session->slot = slot; | |
1780 session->notify = notify; | |
1781 session->appData = pApplication; | |
1782 session->info.flags = flags; | |
1783 session->info.slotID = slotID; | |
1784 session->info.ulDeviceError = 0; | |
1785 sftk_update_state(slot,session); | |
1786 return session; | |
1787 } | |
1788 | |
1789 | |
1790 /* free all the data associated with a session. */ | |
1791 static void | |
1792 sftk_DestroySession(SFTKSession *session) | |
1793 { | |
1794 SFTKObjectList *op,*next; | |
1795 PORT_Assert(session->refCount == 0); | |
1796 | |
1797 /* clean out the attributes */ | |
1798 /* since no one is referencing us, it's safe to walk the chain | |
1799 * without a lock */ | |
1800 for (op = session->objects[0]; op != NULL; op = next) { | |
1801 next = op->next; | |
1802 /* paranoia */ | |
1803 op->next = op->prev = NULL; | |
1804 sftk_DeleteObject(session,op->parent); | |
1805 } | |
1806 PZ_DestroyLock(session->objectLock); | |
1807 if (session->enc_context) { | |
1808 sftk_FreeContext(session->enc_context); | |
1809 } | |
1810 if (session->hash_context) { | |
1811 sftk_FreeContext(session->hash_context); | |
1812 } | |
1813 if (session->sign_context) { | |
1814 sftk_FreeContext(session->sign_context); | |
1815 } | |
1816 if (session->search) { | |
1817 sftk_FreeSearch(session->search); | |
1818 } | |
1819 PORT_Free(session); | |
1820 } | |
1821 | |
1822 | |
1823 /* | |
1824 * look up a session structure from a session handle | |
1825 * generate a reference to it. | |
1826 */ | |
1827 SFTKSession * | |
1828 sftk_SessionFromHandle(CK_SESSION_HANDLE handle) | |
1829 { | |
1830 SFTKSlot *slot = sftk_SlotFromSessionHandle(handle); | |
1831 SFTKSession *session; | |
1832 PZLock *lock; | |
1833 | |
1834 if (!slot) return NULL; | |
1835 lock = SFTK_SESSION_LOCK(slot,handle); | |
1836 | |
1837 PZ_Lock(lock); | |
1838 sftkqueue_find(session,handle,slot->head,slot->sessHashSize); | |
1839 if (session) session->refCount++; | |
1840 PZ_Unlock(lock); | |
1841 | |
1842 return (session); | |
1843 } | |
1844 | |
1845 /* | |
1846 * release a reference to a session handle | |
1847 */ | |
1848 void | |
1849 sftk_FreeSession(SFTKSession *session) | |
1850 { | |
1851 PRBool destroy = PR_FALSE; | |
1852 SFTKSlot *slot = sftk_SlotFromSession(session); | |
1853 PZLock *lock = SFTK_SESSION_LOCK(slot,session->handle); | |
1854 | |
1855 PZ_Lock(lock); | |
1856 if (session->refCount == 1) destroy = PR_TRUE; | |
1857 session->refCount--; | |
1858 PZ_Unlock(lock); | |
1859 | |
1860 if (destroy) sftk_DestroySession(session); | |
1861 } | |
1862 | |
1863 void | |
1864 sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle) | |
1865 { | |
1866 if (search->handles == NULL) { | |
1867 return; | |
1868 } | |
1869 if (search->size >= search->array_size) { | |
1870 search->array_size += NSC_SEARCH_BLOCK_SIZE; | |
1871 search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles, | |
1872 sizeof(CK_OBJECT_HANDLE)* search->array_size); | |
1873 if (search->handles == NULL) { | |
1874 return; | |
1875 } | |
1876 } | |
1877 search->handles[search->size] = handle; | |
1878 search->size++; | |
1879 } | |
1880 | |
1881 static CK_RV | |
1882 handleToClass(SFTKSlot *slot, CK_OBJECT_HANDLE handle, | |
1883 CK_OBJECT_CLASS *objClass) | |
1884 { | |
1885 SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, handle); | |
1886 CK_ATTRIBUTE objClassTemplate; | |
1887 CK_RV crv; | |
1888 | |
1889 *objClass = CKO_DATA; | |
1890 objClassTemplate.type = CKA_CLASS; | |
1891 objClassTemplate.pValue = objClass; | |
1892 objClassTemplate.ulValueLen = sizeof(*objClass); | |
1893 crv = sftkdb_GetAttributeValue(dbHandle, handle, &objClassTemplate, 1); | |
1894 sftk_freeDB(dbHandle); | |
1895 return crv; | |
1896 } | |
1897 | |
1898 SFTKObject * | |
1899 sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle) | |
1900 { | |
1901 SFTKObject *object = NULL; | |
1902 SFTKTokenObject *tokObject = 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 tokObject = (SFTKTokenObject *) object; | |
1912 | |
1913 object->handle = handle; | |
1914 /* every object must have a class, if we can't get it, the object | |
1915 * doesn't exist */ | |
1916 crv = handleToClass(slot, handle, &object->objclass); | |
1917 if (crv != CKR_OK) { | |
1918 goto loser; | |
1919 } | |
1920 object->slot = slot; | |
1921 object->objectInfo = NULL; | |
1922 object->infoFree = NULL; | |
1923 if (!hasLocks) { | |
1924 object->refLock = PZ_NewLock(nssILockRefLock); | |
1925 } | |
1926 if (object->refLock == NULL) { | |
1927 goto loser; | |
1928 } | |
1929 object->refCount = 1; | |
1930 | |
1931 return object; | |
1932 loser: | |
1933 if (object) { | |
1934 (void) sftk_DestroyObject(object); | |
1935 } | |
1936 return NULL; | |
1937 | |
1938 } | |
1939 | |
1940 SFTKTokenObject * | |
1941 sftk_convertSessionToToken(SFTKObject *obj) | |
1942 { | |
1943 SECItem *key; | |
1944 SFTKSessionObject *so = (SFTKSessionObject *)obj; | |
1945 SFTKTokenObject *to = sftk_narrowToTokenObject(obj); | |
1946 SECStatus rv; | |
1947 | |
1948 sftk_DestroySessionObjectData(so); | |
1949 PZ_DestroyLock(so->attributeLock); | |
1950 if (to == NULL) { | |
1951 return NULL; | |
1952 } | |
1953 sftk_tokenKeyLock(so->obj.slot); | |
1954 key = sftk_lookupTokenKeyByHandle(so->obj.slot,so->obj.handle); | |
1955 if (key == NULL) { | |
1956 sftk_tokenKeyUnlock(so->obj.slot); | |
1957 return NULL; | |
1958 } | |
1959 rv = SECITEM_CopyItem(NULL,&to->dbKey,key); | |
1960 sftk_tokenKeyUnlock(so->obj.slot); | |
1961 if (rv == SECFailure) { | |
1962 return NULL; | |
1963 } | |
1964 | |
1965 return to; | |
1966 } | |
1967 | |
1968 SFTKSessionObject * | |
1969 sftk_narrowToSessionObject(SFTKObject *obj) | |
1970 { | |
1971 return !sftk_isToken(obj->handle) ? (SFTKSessionObject *)obj : NULL; | |
1972 } | |
1973 | |
1974 SFTKTokenObject * | |
1975 sftk_narrowToTokenObject(SFTKObject *obj) | |
1976 { | |
1977 return sftk_isToken(obj->handle) ? (SFTKTokenObject *)obj : NULL; | |
1978 } | |
1979 |