1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <pthread.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <security/cryptoki.h>
31 #include "softGlobal.h"
32 #include "softObject.h"
33 #include "softSession.h"
34 #include "softKeystore.h"
35 #include "softKeystoreUtil.h"
36
37 /*
38 * Add an object to the session's object list.
39 *
40 * This function will acquire the lock on the session, and release
41 * that lock after adding the object to the session's object list.
42 */
43 void
soft_add_object_to_session(soft_object_t * objp,soft_session_t * sp)44 soft_add_object_to_session(soft_object_t *objp, soft_session_t *sp)
45 {
46
47 /* Acquire the session lock. */
48 (void) pthread_mutex_lock(&sp->session_mutex);
49
50 /* Insert the new object in front of session's object list. */
51 if (sp->object_list == NULL) {
52 sp->object_list = objp;
53 objp->next = NULL;
54 objp->prev = NULL;
55 } else {
56 sp->object_list->prev = objp;
57 objp->next = sp->object_list;
58 objp->prev = NULL;
59 sp->object_list = objp;
60 }
61
62 /* Release the session lock. */
63 (void) pthread_mutex_unlock(&sp->session_mutex);
64 }
65
66
67 /*
68 * Clean up and release the storage allocated to the object.
69 *
70 * The function is called either with the object lock being held
71 * (by caller soft_delete_object()), or there is no object lock
72 * yet (by soft_build_XXX_object() during creating an object).
73 */
74 void
soft_cleanup_object(soft_object_t * objp)75 soft_cleanup_object(soft_object_t *objp)
76 {
77 /*
78 * Free the storage allocated to big integer attributes.
79 */
80 soft_cleanup_object_bigint_attrs(objp);
81
82 /*
83 * Free the storage allocated to the extra attribute list.
84 */
85 soft_cleanup_extra_attr(objp);
86
87 /*
88 * Free the storage allocated to certificate attributes.
89 */
90 soft_cleanup_cert_object(objp);
91 }
92
93
94 /*
95 * Create a new object. Copy the attributes that can be modified
96 * (in the boolean attribute mask field and extra attribute list)
97 * from the old object to the new object.
98 *
99 * The caller of this function holds the lock on the old object.
100 */
101 CK_RV
soft_copy_object(soft_object_t * old_object,soft_object_t ** new_object,CK_ULONG object_func,soft_session_t * sp)102 soft_copy_object(soft_object_t *old_object, soft_object_t **new_object,
103 CK_ULONG object_func, soft_session_t *sp)
104 {
105
106 CK_RV rv = CKR_OK;
107 soft_object_t *new_objp = NULL;
108 CK_ATTRIBUTE_INFO_PTR attrp;
109
110 /* Allocate new object. */
111 new_objp = calloc(1, sizeof (soft_object_t));
112 if (new_objp == NULL)
113 return (CKR_HOST_MEMORY);
114
115 new_objp->class = old_object->class;
116 new_objp->bool_attr_mask = old_object->bool_attr_mask;
117 new_objp->cert_type = old_object->cert_type;
118 new_objp->object_type = old_object->object_type;
119
120 attrp = old_object->extra_attrlistp;
121 while (attrp) {
122 /*
123 * Copy the attribute_info struct from the old
124 * object to a new attribute_info struct, and add
125 * that new struct to the extra attribute list
126 * of the new object.
127 */
128 rv = soft_copy_extra_attr(attrp, new_objp);
129 if (rv != CKR_OK) {
130 soft_cleanup_extra_attr(new_objp);
131 free(new_objp);
132 return (rv);
133 }
134 attrp = attrp->next;
135 }
136
137 *new_object = new_objp;
138
139 if (object_func == SOFT_SET_ATTR_VALUE) {
140 /* done with copying all information that can be modified */
141 return (CKR_OK);
142 }
143
144 /*
145 * Copy the rest of the object.
146 * Certain fields that are not appropriate for coping will be
147 * initialized.
148 */
149 new_objp->key_type = old_object->key_type;
150 new_objp->magic_marker = old_object->magic_marker;
151 new_objp->mechanism = old_object->mechanism;
152
153 switch (object_func) {
154 case SOFT_COPY_OBJ_ORIG_SH:
155 new_objp->session_handle = old_object->session_handle;
156 break;
157 case SOFT_COPY_OBJECT:
158 /*
159 * Save the session handle of the C_CopyObject function
160 * in the new copy of the session object.
161 */
162 new_objp->session_handle = (CK_SESSION_HANDLE)sp;
163 break;
164 }
165
166 (void) pthread_cond_init(&(new_objp->obj_free_cond), NULL);
167 (void) pthread_mutex_init(&(new_objp->object_mutex), NULL);
168 /* copy key related information */
169 switch (new_objp->class) {
170 case CKO_PUBLIC_KEY:
171 rv = soft_copy_public_key_attr(OBJ_PUB(old_object),
172 &(OBJ_PUB(new_objp)), new_objp->key_type);
173 break;
174 case CKO_PRIVATE_KEY:
175 rv = soft_copy_private_key_attr(OBJ_PRI(old_object),
176 &(OBJ_PRI(new_objp)), new_objp->key_type);
177 break;
178 case CKO_SECRET_KEY:
179 rv = soft_copy_secret_key_attr(OBJ_SEC(old_object),
180 &(OBJ_SEC(new_objp)));
181 break;
182 case CKO_DOMAIN_PARAMETERS:
183 rv = soft_copy_domain_attr(OBJ_DOM(old_object),
184 &(OBJ_DOM(new_objp)), new_objp->key_type);
185 break;
186 case CKO_CERTIFICATE:
187 rv = soft_copy_certificate(OBJ_CERT(old_object),
188 &(OBJ_CERT(new_objp)), new_objp->cert_type);
189 break;
190 default:
191 /* should never be this case */
192 break;
193 }
194 if (rv != CKR_OK) {
195 /*
196 * don't need to cleanup the memory from failure of copying
197 * any key related stuff. Each individual function for
198 * copying key attr will free the memory if it fails
199 */
200 soft_cleanup_extra_attr(new_objp);
201 free(new_objp);
202 }
203 return (rv);
204 }
205
206
207 /*
208 * Copy the attributes (in the boolean attribute mask field and
209 * extra attribute list) from the new object back to the original
210 * object. Also, clean up and release all the storage in the extra
211 * attribute list of the original object.
212 *
213 * The caller of this function holds the lock on the old object.
214 */
215 void
soft_merge_object(soft_object_t * old_object,soft_object_t * new_object)216 soft_merge_object(soft_object_t *old_object, soft_object_t *new_object)
217 {
218 old_object->bool_attr_mask = new_object->bool_attr_mask;
219 soft_cleanup_extra_attr(old_object);
220 old_object->extra_attrlistp = new_object->extra_attrlistp;
221 }
222
223
224 /*
225 * Create a new object struct, and add it to the session's object list.
226 */
227 CK_RV
soft_add_object(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_ULONG * objecthandle_p,soft_session_t * sp)228 soft_add_object(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
229 CK_ULONG *objecthandle_p, soft_session_t *sp)
230 {
231
232 CK_RV rv = CKR_OK;
233 soft_object_t *new_objp = NULL;
234
235 new_objp = calloc(1, sizeof (soft_object_t));
236 if (new_objp == NULL) {
237 return (CKR_HOST_MEMORY);
238 }
239
240 new_objp->extra_attrlistp = NULL;
241
242 /*
243 * Validate attribute template and fill in the attributes
244 * in the soft_object_t.
245 */
246 rv = soft_build_object(pTemplate, ulCount, new_objp);
247 if (rv != CKR_OK) {
248 goto fail_cleanup1;
249 }
250
251 rv = soft_pin_expired_check(new_objp);
252 if (rv != CKR_OK) {
253 goto fail_cleanup2;
254 }
255
256 rv = soft_object_write_access_check(sp, new_objp);
257 if (rv != CKR_OK) {
258 goto fail_cleanup2;
259 }
260
261 /* Initialize the rest of stuffs in soft_object_t. */
262 (void) pthread_cond_init(&new_objp->obj_free_cond, NULL);
263 (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
264 new_objp->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
265 new_objp->obj_refcnt = 0;
266 new_objp->obj_delete_sync = 0;
267
268 /* Write the new token object to the keystore */
269 if (IS_TOKEN_OBJECT(new_objp)) {
270 if (!soft_keystore_status(KEYSTORE_INITIALIZED)) {
271 rv = CKR_DEVICE_REMOVED;
272 goto fail_cleanup2;
273 }
274 new_objp->version = 1;
275 rv = soft_put_object_to_keystore(new_objp);
276 if (rv != CKR_OK) {
277 (void) pthread_cond_destroy(&new_objp->obj_free_cond);
278 (void) pthread_mutex_destroy(&new_objp->object_mutex);
279 goto fail_cleanup2;
280 }
281 new_objp->session_handle = (CK_SESSION_HANDLE)NULL;
282 soft_add_token_object_to_slot(new_objp);
283 /*
284 * Type casting the address of an object struct to
285 * an object handle.
286 */
287 *objecthandle_p = (CK_ULONG)new_objp;
288
289 return (CKR_OK);
290 }
291
292 new_objp->session_handle = (CK_SESSION_HANDLE)sp;
293
294 /* Add the new object to the session's object list. */
295 soft_add_object_to_session(new_objp, sp);
296
297 /* Type casting the address of an object struct to an object handle. */
298 *objecthandle_p = (CK_ULONG)new_objp;
299
300 return (CKR_OK);
301
302 fail_cleanup2:
303 /*
304 * When any error occurs after soft_build_object(), we will need to
305 * clean up the memory allocated by the soft_build_object().
306 */
307 soft_cleanup_object(new_objp);
308
309 fail_cleanup1:
310 if (new_objp) {
311 /*
312 * The storage allocated inside of this object should have
313 * been cleaned up by the soft_build_object() if it failed.
314 * Therefore, we can safely free the object.
315 */
316 free(new_objp);
317 }
318
319 return (rv);
320
321 }
322
323
324 /*
325 * Remove an object from the session's object list.
326 *
327 * The caller of this function holds the session lock.
328 */
329 CK_RV
soft_remove_object_from_session(soft_object_t * objp,soft_session_t * sp)330 soft_remove_object_from_session(soft_object_t *objp, soft_session_t *sp)
331 {
332 soft_object_t *tmp_objp;
333 boolean_t found = B_FALSE;
334
335 /*
336 * Remove the object from the session's object list.
337 */
338 if ((sp == NULL) ||
339 (sp->magic_marker != SOFTTOKEN_SESSION_MAGIC)) {
340 return (CKR_SESSION_HANDLE_INVALID);
341 }
342
343 if ((sp->object_list == NULL) || (objp == NULL) ||
344 (objp->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
345 return (CKR_OBJECT_HANDLE_INVALID);
346 }
347
348 tmp_objp = sp->object_list;
349 while (tmp_objp) {
350 if (tmp_objp == objp) {
351 found = B_TRUE;
352 break;
353 }
354 tmp_objp = tmp_objp->next;
355 }
356 if (!found)
357 return (CKR_OBJECT_HANDLE_INVALID);
358
359 if (sp->object_list == objp) {
360 /* Object is the first one in the list. */
361 if (objp->next) {
362 sp->object_list = objp->next;
363 objp->next->prev = NULL;
364 } else {
365 /* Object is the only one in the list. */
366 sp->object_list = NULL;
367 }
368 } else {
369 /* Object is not the first one in the list. */
370 if (objp->next) {
371 /* Object is in the middle of the list. */
372 objp->prev->next = objp->next;
373 objp->next->prev = objp->prev;
374 } else {
375 /* Object is the last one in the list. */
376 objp->prev->next = NULL;
377 }
378 }
379 return (CKR_OK);
380 }
381
382 /*
383 * This function adds the to-be-freed session object to a linked list.
384 * When the number of objects queued in the linked list reaches the
385 * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
386 * object (FIFO) in the list.
387 */
388 void
object_delay_free(soft_object_t * objp)389 object_delay_free(soft_object_t *objp)
390 {
391 soft_object_t *tmp;
392
393 (void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
394
395 /* Add the newly deleted object at the end of the list */
396 objp->next = NULL;
397 if (obj_delay_freed.first == NULL) {
398 obj_delay_freed.last = objp;
399 obj_delay_freed.first = objp;
400 } else {
401 obj_delay_freed.last->next = objp;
402 obj_delay_freed.last = objp;
403 }
404
405 if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
406 /*
407 * Free the first object in the list only if
408 * the total count reaches maximum threshold.
409 */
410 obj_delay_freed.count--;
411 tmp = obj_delay_freed.first->next;
412 free(obj_delay_freed.first);
413 obj_delay_freed.first = tmp;
414 }
415 (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
416 }
417
418 static void
soft_delete_object_cleanup(soft_object_t * objp,boolean_t force)419 soft_delete_object_cleanup(soft_object_t *objp, boolean_t force)
420 {
421 /* Acquire the lock on the object. */
422 (void) pthread_mutex_lock(&objp->object_mutex);
423
424 /*
425 * Make sure another thread hasn't freed the object.
426 */
427 if (objp->magic_marker != SOFTTOKEN_OBJECT_MAGIC) {
428 (void) pthread_mutex_unlock(&objp->object_mutex);
429 return;
430 }
431
432 /*
433 * The deletion of an object must be blocked when the object
434 * reference count is not zero. This means if any object related
435 * operation starts prior to the delete object operation gets in,
436 * the object deleting thread must wait for the non-deleting
437 * operation to be completed before it can proceed the delete
438 * operation.
439 *
440 * Unless we are being forced to shut everything down, this only
441 * happens if the libraries _fini() is running not of someone
442 * explicitly called C_Finalize().
443 */
444 if (force)
445 objp->obj_refcnt = 0;
446
447 while (objp->obj_refcnt != 0) {
448 /*
449 * We set the OBJECT_REFCNT_WAITING flag before we put
450 * this deleting thread in a wait state, so other non-deleting
451 * operation thread will signal to wake it up only when
452 * the object reference count becomes zero and this flag
453 * is set.
454 */
455 objp->obj_delete_sync |= OBJECT_REFCNT_WAITING;
456 (void) pthread_cond_wait(&objp->obj_free_cond,
457 &objp->object_mutex);
458 }
459
460 objp->obj_delete_sync &= ~OBJECT_REFCNT_WAITING;
461
462 /* Mark object as no longer valid. */
463 objp->magic_marker = 0;
464
465 (void) pthread_cond_destroy(&objp->obj_free_cond);
466
467 /*
468 * Cleanup the contents of this object such as free all the
469 * storage allocated for this object.
470 */
471 soft_cleanup_object(objp);
472
473 /* Reset OBJECT_IS_DELETING flag. */
474 objp->obj_delete_sync &= ~OBJECT_IS_DELETING;
475
476 (void) pthread_mutex_unlock(&objp->object_mutex);
477 /* Destroy the object lock */
478 (void) pthread_mutex_destroy(&objp->object_mutex);
479
480 /* Free the object itself */
481 if (IS_TOKEN_OBJECT(objp))
482 free(objp);
483 else
484 /*
485 * Delay freeing the session object as S1WS/NSS uses session
486 * objects for its SSL Handshake.
487 */
488 (void) object_delay_free(objp);
489 }
490
491 /*
492 * Delete an object:
493 * - Remove the object from the session's object list.
494 * Holding the lock on the session which the object was created at
495 * is needed to do this.
496 * - Release the storage allocated to the object.
497 *
498 * The boolean argument lock_held is used to indicate that whether
499 * the caller holds the session lock or not.
500 * - When called by soft_delete_all_objects_in_session() -- the
501 * lock_held = TRUE.
502 *
503 * When the caller does not hold the session lock, this function
504 * will acquire that lock in order to proceed, and also release
505 * that lock before returning to caller.
506 */
507 void
soft_delete_object(soft_session_t * sp,soft_object_t * objp,boolean_t force,boolean_t lock_held)508 soft_delete_object(soft_session_t *sp, soft_object_t *objp,
509 boolean_t force, boolean_t lock_held)
510 {
511
512 /*
513 * Check to see if the caller holds the lock on the session.
514 * If not, we need to acquire that lock in order to proceed.
515 */
516 if (!lock_held) {
517 /* Acquire the session lock. */
518 (void) pthread_mutex_lock(&sp->session_mutex);
519 }
520
521 /* Remove the object from the session's object list first. */
522 if (soft_remove_object_from_session(objp, sp) != CKR_OK) {
523 if (!lock_held) {
524 (void) pthread_mutex_unlock(&sp->session_mutex);
525 }
526 return;
527 }
528
529 if (!lock_held) {
530 /*
531 * If the session lock is obtained by this function,
532 * then release that lock after removing the object
533 * from session's object list.
534 * We want the releasing of the object storage to
535 * be done without holding the session lock.
536 */
537 (void) pthread_mutex_unlock(&sp->session_mutex);
538 }
539
540 soft_delete_object_cleanup(objp, force);
541 }
542
543
544 /*
545 * Delete all the objects in a session. The caller holds the lock
546 * on the session.
547 */
548 void
soft_delete_all_objects_in_session(soft_session_t * sp,boolean_t force)549 soft_delete_all_objects_in_session(soft_session_t *sp, boolean_t force)
550 {
551 soft_object_t *objp = sp->object_list;
552 soft_object_t *objp1;
553
554 /* Delete all the objects in the session. */
555 while (objp) {
556 objp1 = objp->next;
557
558 /*
559 * Delete an object by calling soft_delete_object()
560 * with a TRUE boolean argument indicating that
561 * the caller holds the lock on the session.
562 */
563 soft_delete_object(sp, objp, force, B_TRUE);
564
565 objp = objp1;
566 }
567 }
568
569 static CK_RV
add_to_search_result(soft_object_t * obj,find_context_t * fcontext,CK_ULONG * num_result_alloc)570 add_to_search_result(soft_object_t *obj, find_context_t *fcontext,
571 CK_ULONG *num_result_alloc)
572 {
573 /*
574 * allocate space for storing results if the currently
575 * allocated space is not enough
576 */
577 if (*num_result_alloc <= fcontext->num_results) {
578 fcontext->objs_found = realloc(fcontext->objs_found,
579 sizeof (soft_object_t *) * (*num_result_alloc + BUFSIZ));
580 if (fcontext->objs_found == NULL) {
581 return (CKR_HOST_MEMORY);
582 }
583 *num_result_alloc += BUFSIZ;
584 }
585
586 (fcontext->objs_found)[(fcontext->num_results)++] = obj;
587 return (CKR_OK);
588 }
589
590 static CK_RV
search_for_objects(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,find_context_t * fcontext)591 search_for_objects(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
592 find_context_t *fcontext)
593 {
594 soft_session_t *session_p;
595 soft_object_t *obj;
596 CK_OBJECT_CLASS pclasses[6]; /* classes attrs possibly exist */
597 CK_ULONG num_pclasses; /* number of possible classes */
598 CK_ULONG num_result_alloc = 0; /* spaces allocated for results */
599 CK_RV rv = CKR_OK;
600 /* whether CKA_TOKEN flag specified or not */
601 boolean_t token_specified = B_FALSE;
602 /* value of CKA_TOKEN flag, if specified */
603 boolean_t token_flag_val = B_FALSE;
604 CK_ULONG i;
605
606 if (ulCount > 0) {
607 /* there are some search requirement */
608 soft_process_find_attr(pclasses, &num_pclasses,
609 pTemplate, ulCount);
610 }
611
612 for (i = 0; i < ulCount; i++) {
613 if (pTemplate[i].type == CKA_PRIVATE) {
614 (void) pthread_mutex_lock(&soft_giant_mutex);
615 if (soft_slot.userpin_change_needed) {
616 (void) pthread_mutex_unlock(&soft_giant_mutex);
617 return (CKR_PIN_EXPIRED);
618 }
619 (void) pthread_mutex_unlock(&soft_giant_mutex);
620 }
621 }
622
623 /*
624 * look through template and see if it explicitly specifies
625 * whether we need to look for token objects or not
626 */
627 for (i = 0; i < ulCount; i++) {
628 if (pTemplate[i].type == CKA_TOKEN) {
629 token_specified = B_TRUE;
630 token_flag_val = *((CK_BBOOL *)pTemplate[i].pValue);
631 break;
632 }
633 }
634
635 /*
636 * Need go through token objects if it explicitly say so, or
637 * it is not mentioned in the template. And this will ONLY be
638 * done when the keystore exists. Otherwise, we will skip re-loading
639 * the token objects.
640 *
641 * If a session has not logged into the token, only public
642 * objects, if any, will be searched. If a session is logged
643 * into the token, all public and private objects in the keystore
644 * are searched.
645 */
646 if (((token_flag_val) || (!token_specified)) &&
647 soft_keystore_status(KEYSTORE_INITIALIZED)) {
648 /* acquire token session lock */
649 (void) pthread_mutex_lock(&soft_slot.slot_mutex);
650 rv = refresh_token_objects();
651 if (rv != CKR_OK) {
652 (void) pthread_mutex_unlock(&soft_slot.slot_mutex);
653 return (rv);
654 }
655 obj = soft_slot.token_object_list;
656 while (obj) {
657 (void) pthread_mutex_lock(&obj->object_mutex);
658 if (((token_specified) && (ulCount > 1)) ||
659 ((!token_specified) && (ulCount > 0))) {
660 if (soft_find_match_attrs(obj, pclasses,
661 num_pclasses, pTemplate, ulCount)) {
662 rv = add_to_search_result(
663 obj, fcontext, &num_result_alloc);
664 }
665 } else {
666 /* no search criteria, just record the object */
667 rv = add_to_search_result(obj, fcontext,
668 &num_result_alloc);
669 }
670 (void) pthread_mutex_unlock(&obj->object_mutex);
671 if (rv != CKR_OK) {
672 (void) pthread_mutex_unlock
673 (&soft_slot.slot_mutex);
674 return (rv);
675 }
676 obj = obj->next;
677 }
678 (void) pthread_mutex_unlock(&soft_slot.slot_mutex);
679 }
680
681 if (token_flag_val) {
682 /* no need to look through session objects */
683 return (rv);
684 }
685
686 /* Acquire the global session list lock */
687 (void) pthread_mutex_lock(&soft_sessionlist_mutex);
688
689 /*
690 * Go through all objects in each session.
691 * Acquire individual session lock for the session
692 * we are searching.
693 */
694 session_p = soft_session_list;
695 while (session_p) {
696 (void) pthread_mutex_lock(&session_p->session_mutex);
697
698 obj = session_p->object_list;
699 while (obj) {
700 (void) pthread_mutex_lock(&obj->object_mutex);
701 if (ulCount > 0) {
702 if (soft_find_match_attrs(obj, pclasses,
703 num_pclasses, pTemplate, ulCount)) {
704 rv = add_to_search_result(
705 obj, fcontext, &num_result_alloc);
706 }
707 } else {
708 /* no search criteria, just record the object */
709 rv = add_to_search_result(obj, fcontext,
710 &num_result_alloc);
711 }
712 (void) pthread_mutex_unlock(&obj->object_mutex);
713 if (rv != CKR_OK) {
714 (void) pthread_mutex_unlock(
715 &session_p->session_mutex);
716 goto cleanup;
717 }
718 obj = obj->next;
719 }
720 (void) pthread_mutex_unlock(&session_p->session_mutex);
721 session_p = session_p->next;
722 }
723
724 cleanup:
725 /* Release the global session list lock */
726 (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
727 return (rv);
728 }
729
730 /*
731 * Initialize the context for C_FindObjects() calls
732 */
733 CK_RV
soft_find_objects_init(soft_session_t * sp,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)734 soft_find_objects_init(soft_session_t *sp, CK_ATTRIBUTE_PTR pTemplate,
735 CK_ULONG ulCount)
736 {
737
738 CK_RV rv = CKR_OK;
739 CK_OBJECT_CLASS class; /* for soft_validate_attr(). Value unused */
740 find_context_t *fcontext;
741
742 if (ulCount) {
743 rv = soft_validate_attr(pTemplate, ulCount, &class);
744 /* Make sure all attributes in template are valid */
745 if (rv != CKR_OK) {
746 return (rv);
747 }
748 }
749
750
751 /* prepare the find context */
752 fcontext = calloc(1, sizeof (find_context_t));
753 if (fcontext == NULL) {
754 return (CKR_HOST_MEMORY);
755 }
756
757 rv = search_for_objects(pTemplate, ulCount, fcontext);
758 if (rv != CKR_OK) {
759 free(fcontext);
760 return (rv);
761 }
762
763 /* store the find_context in the session */
764 sp->find_objects.context = (CK_VOID_PTR)fcontext;
765
766 return (rv);
767 }
768
769 void
soft_find_objects_final(soft_session_t * sp)770 soft_find_objects_final(soft_session_t *sp)
771 {
772 find_context_t *fcontext;
773
774 fcontext = sp->find_objects.context;
775 sp->find_objects.context = NULL;
776 sp->find_objects.flags = 0;
777 if (fcontext->objs_found != NULL) {
778 free(fcontext->objs_found);
779 }
780
781 free(fcontext);
782 }
783
784 void
soft_find_objects(soft_session_t * sp,CK_OBJECT_HANDLE * obj_found,CK_ULONG max_obj_requested,CK_ULONG * found_obj_count)785 soft_find_objects(soft_session_t *sp, CK_OBJECT_HANDLE *obj_found,
786 CK_ULONG max_obj_requested, CK_ULONG *found_obj_count)
787 {
788 find_context_t *fcontext;
789 CK_ULONG num_obj_found = 0;
790 CK_ULONG i;
791 soft_object_t *obj;
792
793 fcontext = sp->find_objects.context;
794
795 for (i = fcontext->next_result_index;
796 ((num_obj_found < max_obj_requested) &&
797 (i < fcontext->num_results));
798 i++) {
799 obj = fcontext->objs_found[i];
800 if (obj != NULL) {
801 (void) pthread_mutex_lock(&obj->object_mutex);
802 /* a sanity check to make sure the obj is still valid */
803 if (obj->magic_marker == SOFTTOKEN_OBJECT_MAGIC) {
804 obj_found[num_obj_found] =
805 (CK_OBJECT_HANDLE)obj;
806 num_obj_found++;
807 }
808 (void) pthread_mutex_unlock(&obj->object_mutex);
809 }
810 }
811 fcontext->next_result_index = i;
812 *found_obj_count = num_obj_found;
813 }
814
815 /*
816 * Below are the token object related functions
817 */
818 void
soft_add_token_object_to_slot(soft_object_t * objp)819 soft_add_token_object_to_slot(soft_object_t *objp)
820 {
821
822 (void) pthread_mutex_lock(&soft_slot.slot_mutex);
823
824 /* Insert the new object in front of slot's token object list. */
825 if (soft_slot.token_object_list == NULL) {
826 soft_slot.token_object_list = objp;
827 objp->next = NULL;
828 objp->prev = NULL;
829 } else {
830 soft_slot.token_object_list->prev = objp;
831 objp->next = soft_slot.token_object_list;
832 objp->prev = NULL;
833 soft_slot.token_object_list = objp;
834 }
835
836 (void) pthread_mutex_unlock(&soft_slot.slot_mutex);
837
838 }
839
840 void
soft_remove_token_object_from_slot(soft_object_t * objp,boolean_t lock_held)841 soft_remove_token_object_from_slot(soft_object_t *objp, boolean_t lock_held)
842 {
843
844 if (!lock_held)
845 (void) pthread_mutex_lock(&soft_slot.slot_mutex);
846
847 /*
848 * Remove the object from the slot's token object list.
849 */
850 if (soft_slot.token_object_list == objp) {
851 /* Object is the first one in the list. */
852 if (objp->next) {
853 soft_slot.token_object_list = objp->next;
854 objp->next->prev = NULL;
855 } else {
856 /* Object is the only one in the list. */
857 soft_slot.token_object_list = NULL;
858 }
859 } else {
860 /* Object is not the first one in the list. */
861 if (objp->next) {
862 /* Object is in the middle of the list. */
863 objp->prev->next = objp->next;
864 objp->next->prev = objp->prev;
865 } else {
866 /* Object is the last one in the list. */
867 objp->prev->next = NULL;
868 }
869 }
870
871 if (!lock_held)
872 (void) pthread_mutex_unlock(&soft_slot.slot_mutex);
873 }
874
875 void
soft_delete_token_object(soft_object_t * objp,boolean_t persistent,boolean_t lock_held)876 soft_delete_token_object(soft_object_t *objp, boolean_t persistent,
877 boolean_t lock_held)
878 {
879
880 if (!lock_held)
881 (void) pthread_mutex_lock(&soft_slot.slot_mutex);
882 if (persistent)
883 /* Delete the object from the keystore. */
884 (void) soft_keystore_del_obj(&objp->ks_handle, B_FALSE);
885
886 /* Remove the object from the slot's token object list. */
887 soft_remove_token_object_from_slot(objp, B_TRUE);
888 if (!lock_held)
889 (void) pthread_mutex_unlock(&soft_slot.slot_mutex);
890
891 soft_delete_object_cleanup(objp, B_FALSE);
892 }
893
894 void
soft_delete_all_in_core_token_objects(token_obj_type_t type)895 soft_delete_all_in_core_token_objects(token_obj_type_t type)
896 {
897
898 soft_object_t *objp;
899 soft_object_t *objp1;
900
901 (void) pthread_mutex_lock(&soft_slot.slot_mutex);
902 objp = soft_slot.token_object_list;
903
904 switch (type) {
905 case PRIVATE_TOKEN:
906 while (objp) {
907 objp1 = objp->next;
908 if (objp->object_type == TOKEN_PRIVATE) {
909 soft_delete_token_object(objp, B_FALSE, B_TRUE);
910 }
911 objp = objp1;
912 }
913 break;
914
915 case PUBLIC_TOKEN:
916 while (objp) {
917 objp1 = objp->next;
918 if (objp->object_type == TOKEN_PUBLIC) {
919 soft_delete_token_object(objp, B_FALSE, B_TRUE);
920 }
921 objp = objp1;
922 }
923 break;
924
925 case ALL_TOKEN:
926 while (objp) {
927 objp1 = objp->next;
928 soft_delete_token_object(objp, B_FALSE, B_TRUE);
929 objp = objp1;
930 }
931 break;
932 }
933
934 (void) pthread_mutex_unlock(&soft_slot.slot_mutex);
935
936 }
937
938 /*
939 * Mark all the token objects in the global list to be valid.
940 */
941 void
soft_validate_token_objects(boolean_t validate)942 soft_validate_token_objects(boolean_t validate)
943 {
944
945 soft_object_t *objp;
946
947 (void) pthread_mutex_lock(&soft_slot.slot_mutex);
948
949 objp = soft_slot.token_object_list;
950
951 while (objp) {
952 if (validate)
953 objp->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
954 else
955 objp->magic_marker = 0;
956
957 objp = objp->next;
958 }
959
960 (void) pthread_mutex_unlock(&soft_slot.slot_mutex);
961
962 }
963
964 /*
965 * Verify user's write access rule to the token object.
966 */
967 CK_RV
soft_object_write_access_check(soft_session_t * sp,soft_object_t * objp)968 soft_object_write_access_check(soft_session_t *sp, soft_object_t *objp)
969 {
970
971 /*
972 * This function is called by C_CreateObject, C_CopyObject,
973 * C_DestroyObject, C_SetAttributeValue, C_GenerateKey,
974 * C_GenerateKeyPairs, C_DeriveKey. All of them will write
975 * the token object to the keystore.
976 */
977 (void) pthread_mutex_lock(&soft_giant_mutex);
978 if (!soft_slot.authenticated) {
979 (void) pthread_mutex_unlock(&soft_giant_mutex);
980 /* User is not logged in */
981 if (sp->flags & CKF_RW_SESSION) {
982 /*
983 * For R/W Public Session:
984 * we allow write access to public session or token
985 * object, but not for private token/session object.
986 */
987 if ((objp->object_type == TOKEN_PRIVATE) ||
988 (objp->object_type == SESSION_PRIVATE)) {
989 return (CKR_USER_NOT_LOGGED_IN);
990 }
991 } else {
992 /*
993 * For R/O Public Session:
994 * we allow write access to public session object.
995 */
996 if (objp->object_type != SESSION_PUBLIC)
997 return (CKR_SESSION_READ_ONLY);
998 }
999 } else {
1000 (void) pthread_mutex_unlock(&soft_giant_mutex);
1001 /* User is logged in */
1002 if (!(sp->flags & CKF_RW_SESSION)) {
1003 /*
1004 * For R/O User Function Session:
1005 * we allow write access to public or private
1006 * session object, but not for public or private
1007 * token object.
1008 */
1009 if ((objp->object_type == TOKEN_PUBLIC) ||
1010 (objp->object_type == TOKEN_PRIVATE)) {
1011 return (CKR_SESSION_READ_ONLY);
1012 }
1013 }
1014 }
1015
1016 return (CKR_OK);
1017 }
1018
1019 /*
1020 * Verify if user is required to setpin when accessing the
1021 * private token/session object.
1022 */
1023 CK_RV
soft_pin_expired_check(soft_object_t * objp)1024 soft_pin_expired_check(soft_object_t *objp)
1025 {
1026
1027 /*
1028 * This function is called by C_CreateObject, C_CopyObject,
1029 * C_DestroyObject, C_GenerateKey,
1030 * C_GenerateKeyPairs, C_DeriveKey.
1031 * All of them will return CKR_PIN_EXPIRED if the
1032 * "userpin_change_needed" is set.
1033 *
1034 * The following functions will not be necessary to call
1035 * this routine even though CKR_PIN_EXPIRED is one of the
1036 * valid error code they might return. These functions are:
1037 * C_EncryptInit, C_DecryptInit, C_DigestInit, C_SignInit,
1038 * C_SignRecoverInit, C_VerifyInit, C_VerifyRecoverInit.
1039 * This is because they will not get the object handle
1040 * before the above functions are called.
1041 */
1042
1043 (void) pthread_mutex_lock(&soft_giant_mutex);
1044 if (soft_slot.userpin_change_needed) {
1045 /*
1046 * Access private token/session object but user's
1047 * PIN is expired or never set.
1048 */
1049 if ((objp->object_type == TOKEN_PRIVATE) ||
1050 (objp->object_type == SESSION_PRIVATE)) {
1051 (void) pthread_mutex_unlock(&soft_giant_mutex);
1052 return (CKR_PIN_EXPIRED);
1053 }
1054 }
1055
1056 (void) pthread_mutex_unlock(&soft_giant_mutex);
1057 return (CKR_OK);
1058 }
1059
1060 /*
1061 * Copy the selected fields from new token object to old
1062 * token object.
1063 */
1064 CK_RV
soft_copy_to_old_object(soft_object_t * new,soft_object_t * old)1065 soft_copy_to_old_object(soft_object_t *new, soft_object_t *old)
1066 {
1067
1068 CK_RV rv = CKR_OK;
1069 CK_ATTRIBUTE_INFO_PTR attrp;
1070
1071 old->class = new->class;
1072 old->bool_attr_mask = new->bool_attr_mask;
1073 soft_cleanup_extra_attr(old);
1074 attrp = new->extra_attrlistp;
1075 while (attrp) {
1076 rv = soft_copy_extra_attr(attrp, old);
1077 if (rv != CKR_OK) {
1078 soft_cleanup_extra_attr(old);
1079 return (rv);
1080 }
1081 attrp = attrp->next;
1082 }
1083
1084 /* Done with copying all information that can be modified */
1085 return (CKR_OK);
1086 }
1087
1088 /*
1089 * Update an existing object with new data from keystore.
1090 */
1091 CK_RV
soft_update_object(ks_obj_t * ks_obj,soft_object_t * old_obj)1092 soft_update_object(ks_obj_t *ks_obj, soft_object_t *old_obj)
1093 {
1094
1095 soft_object_t *new_object;
1096 CK_RV rv;
1097
1098 new_object = calloc(1, sizeof (soft_object_t));
1099 if (new_object == NULL)
1100 return (CKR_HOST_MEMORY);
1101
1102 rv = soft_keystore_unpack_obj(new_object, ks_obj);
1103 if (rv != CKR_OK) {
1104 soft_cleanup_object(new_object);
1105 free(new_object);
1106 return (rv);
1107 }
1108 rv = soft_copy_to_old_object(new_object, old_obj);
1109
1110 soft_cleanup_object(new_object);
1111 free(new_object);
1112 return (CKR_OK);
1113 }
1114
1115
1116 CK_RV
soft_keystore_load_latest_object(soft_object_t * old_obj)1117 soft_keystore_load_latest_object(soft_object_t *old_obj)
1118 {
1119
1120 uint_t version;
1121 ks_obj_t *ks_obj = NULL;
1122 CK_RV rv = CKR_OK;
1123
1124 /*
1125 * Get the current version number from the keystore for
1126 * the specified token object.
1127 */
1128 if (soft_keystore_get_object_version(&old_obj->ks_handle, &version,
1129 B_FALSE) == 1)
1130 return (CKR_FUNCTION_FAILED);
1131
1132 /*
1133 * If the keystore version is newer than the in-core version,
1134 * re-read the token object from the keystore.
1135 */
1136 if (old_obj->version != version) {
1137 rv = soft_keystore_get_single_obj(&old_obj->ks_handle,
1138 &ks_obj, B_FALSE);
1139 if (rv != CKR_OK)
1140 return (rv);
1141 old_obj->version = version;
1142
1143 /*
1144 * Update an existing object with new data from keystore.
1145 */
1146 rv = soft_update_object(ks_obj, old_obj);
1147 free(ks_obj->buf);
1148 free(ks_obj);
1149 }
1150
1151 return (rv);
1152 }
1153
1154 /*
1155 * Insert an object into a list of soft_object_t objects. It is assumed
1156 * that the object to be inserted doesn't previously belong to any list
1157 */
1158 static void
insert_into_list(soft_object_t ** list,soft_object_t ** end_of_list,soft_object_t * objp)1159 insert_into_list(soft_object_t **list, soft_object_t **end_of_list,
1160 soft_object_t *objp)
1161 {
1162 if (*list == NULL) {
1163 *list = objp;
1164 objp->next = NULL;
1165 objp->prev = NULL;
1166 *end_of_list = objp;
1167 } else {
1168 (*list)->prev = objp;
1169 objp->next = *list;
1170 objp->prev = NULL;
1171 *list = objp;
1172 }
1173 }
1174
1175 /*
1176 * Move an object from an existing list into a new list of
1177 * soft_object_t objects.
1178 */
1179 static void
move_into_list(soft_object_t ** existing_list,soft_object_t ** new_list,soft_object_t ** end_of_list,soft_object_t * objp)1180 move_into_list(soft_object_t **existing_list, soft_object_t **new_list,
1181 soft_object_t **end_of_list, soft_object_t *objp)
1182 {
1183
1184 /* first, remove object from existing list */
1185 if (objp == *existing_list) {
1186 /* first item in list */
1187 if (objp->next) {
1188 *existing_list = objp->next;
1189 objp->next->prev = NULL;
1190 } else {
1191 *existing_list = NULL;
1192 }
1193 } else {
1194 if (objp->next) {
1195 objp->prev->next = objp->next;
1196 objp->next->prev = objp->prev;
1197 } else {
1198 objp->prev->next = NULL;
1199 }
1200 }
1201
1202 /* then, add into new list */
1203 insert_into_list(new_list, end_of_list, objp);
1204 }
1205
1206 /*
1207 * Insert "new_list" into "existing_list", new list will always be inserted
1208 * into the front of existing list
1209 */
1210 static void
insert_list_into_list(soft_object_t ** existing_list,soft_object_t * new_list,soft_object_t * end_new_list)1211 insert_list_into_list(soft_object_t **existing_list,
1212 soft_object_t *new_list, soft_object_t *end_new_list)
1213 {
1214
1215 if (new_list == NULL) {
1216 return;
1217 }
1218
1219 if (*existing_list == NULL) {
1220 *existing_list = new_list;
1221 } else {
1222 (*existing_list)->prev = end_new_list;
1223 end_new_list->next = *existing_list;
1224 *existing_list = new_list;
1225 }
1226 }
1227
1228 static void
delete_all_objs_in_list(soft_object_t * list)1229 delete_all_objs_in_list(soft_object_t *list)
1230 {
1231 soft_object_t *objp, *objp_next;
1232
1233 if (list == NULL) {
1234 return;
1235 }
1236
1237 objp = list;
1238 while (objp) {
1239 objp_next = objp->next;
1240 soft_delete_object_cleanup(objp, B_FALSE);
1241 objp = objp_next;
1242 }
1243 }
1244
1245 /*
1246 * Makes sure that the list of in-core token objects are up to date
1247 * with respect to the on disk keystore. Other process/applications
1248 * might have modified the keystore since the objects are last loaded
1249 *
1250 * If there's any error from refreshing the token object list (eg: unable
1251 * to read, unable to unpack and object...etc), the in-core list
1252 * will be restored back to the state before the refresh. An error
1253 * will be returned to indicate the failure.
1254 *
1255 * It is assumed that the caller holds the lock for the token slot
1256 */
1257 CK_RV
refresh_token_objects()1258 refresh_token_objects()
1259 {
1260 uint_t on_disk_ks_version;
1261 ks_obj_t *on_disk_list = NULL, *tmp_on_disk, *next_on_disk;
1262 soft_object_t *in_core_obj, *tmp_incore_obj, *new_objp = NULL;
1263 CK_RV rv = CKR_OK;
1264
1265 /* deleted in-core objects */
1266 soft_object_t *del_objs_list = NULL;
1267 soft_object_t *end_del_objs_list = NULL;
1268
1269 /* modified in-core objects */
1270 soft_object_t *mod_objs_list = NULL;
1271 soft_object_t *end_mod_objs_list = NULL;
1272
1273 /*
1274 * copy of modified in-core objects, in case we need
1275 * undo the change
1276 */
1277 soft_object_t *copy_of_mod_objs_list = NULL;
1278 soft_object_t *end_copy_of_mod_objs_list = NULL;
1279
1280 /* objects to be added to the in-core list */
1281 soft_object_t *added_objs_list = NULL;
1282 soft_object_t *end_added_objs_list = NULL;
1283
1284 if (soft_keystore_get_version(&on_disk_ks_version, B_FALSE) != 0) {
1285 return (CKR_FUNCTION_FAILED);
1286 }
1287
1288 (void) pthread_mutex_lock(&soft_giant_mutex);
1289 if (on_disk_ks_version == soft_slot.ks_version) {
1290 /* no change */
1291 (void) pthread_mutex_unlock(&soft_giant_mutex);
1292 return (CKR_OK);
1293 }
1294
1295 if (soft_slot.authenticated) {
1296 /* get both public and private objects */
1297 (void) pthread_mutex_unlock(&soft_giant_mutex);
1298 rv = soft_keystore_get_objs(ALL_TOKENOBJS, &on_disk_list,
1299 B_FALSE);
1300 } else {
1301 /* get both public objects only */
1302 (void) pthread_mutex_unlock(&soft_giant_mutex);
1303 rv = soft_keystore_get_objs(PUB_TOKENOBJS, &on_disk_list,
1304 B_FALSE);
1305 }
1306 if (rv != CKR_OK) {
1307 return (rv);
1308 }
1309
1310 /*
1311 * The in-core tokens list will be updated as follows:
1312 *
1313 * Go through each item in the in-core tokens list.
1314 * Try to match the in-core object with one of the
1315 * objects from the on-disk list. If a match is made,
1316 * check the version number, and update in-core object
1317 * as necessary.
1318 *
1319 * If there's no match between in-core object with on-disk
1320 * object, that means the object is deleted since
1321 * last loaded. Will remove object from in-core list.
1322 *
1323 * When doing the matching of on-disk object list above,
1324 * Delete every matched on-disk object from the on-disk list
1325 * regardless the in-core object need to be deleted or not
1326 *
1327 * At the end of matching the in-core tokens list, if
1328 * any object is still left on the on-disk object list,
1329 * those are all new objects added since last load,
1330 * include all of them to the in-core list
1331 *
1332 * Since we need to be able to revert the in-core list
1333 * back to original state if there's any error with the refresh,
1334 * we need to do the following.
1335 * When an in-core object is "deleted", it is not immediately
1336 * deleted. It is moved to the list of "deleted_objects".
1337 * When an in-core object is "modified", a copy of the
1338 * unmodified object is made. After the object is modified,
1339 * it is temporarily moved to the "mod_objects" list
1340 * from the in-core list.
1341 * When the refresh is completed without any error,
1342 * the actual deleted objects and unmodified objects is deleted.
1343 */
1344 in_core_obj = soft_slot.token_object_list;
1345 while (in_core_obj) {
1346 /* try to match object with on_disk_list */
1347 ks_obj_t *ondisk_obj, *prev_ondisk_obj;
1348 boolean_t found = B_FALSE;
1349 soft_object_t *obj_copy;
1350
1351 ondisk_obj = on_disk_list;
1352 prev_ondisk_obj = NULL;
1353
1354 /* larval object that has not been written to disk */
1355 if (in_core_obj->ks_handle.name[0] == '\0') {
1356 in_core_obj = in_core_obj->next;
1357 continue;
1358 }
1359
1360 while ((!found) && (ondisk_obj != NULL)) {
1361
1362 if (strcmp((char *)((ondisk_obj->ks_handle).name),
1363 (char *)((in_core_obj->ks_handle).name)) == 0) {
1364
1365 /* found a match */
1366 found = B_TRUE;
1367
1368 /* update in-core obj if necessary */
1369 if (ondisk_obj->obj_version !=
1370 in_core_obj->version) {
1371 /* make a copy of before updating */
1372 rv = soft_copy_object(in_core_obj,
1373 &obj_copy, SOFT_COPY_OBJ_ORIG_SH,
1374 NULL);
1375 if (rv != CKR_OK) {
1376 goto cleanup;
1377 }
1378 insert_into_list(
1379 ©_of_mod_objs_list,
1380 &end_copy_of_mod_objs_list,
1381 obj_copy);
1382
1383 rv = soft_update_object(ondisk_obj,
1384 in_core_obj);
1385 if (rv != CKR_OK) {
1386 goto cleanup;
1387 }
1388 move_into_list(
1389 &(soft_slot.token_object_list),
1390 &mod_objs_list, &end_mod_objs_list,
1391 in_core_obj);
1392 }
1393
1394 /* remove processed obj from on disk list */
1395 if (ondisk_obj == on_disk_list) {
1396 /* first item */
1397 on_disk_list = ondisk_obj->next;
1398 } else {
1399 prev_ondisk_obj->next =
1400 ondisk_obj->next;
1401 }
1402 free(ondisk_obj->buf);
1403 free(ondisk_obj);
1404 } else {
1405 prev_ondisk_obj = ondisk_obj;
1406 ondisk_obj = ondisk_obj->next;
1407 }
1408 }
1409
1410 if (!found) {
1411 tmp_incore_obj = in_core_obj->next;
1412 move_into_list(&(soft_slot.token_object_list),
1413 &del_objs_list, &end_del_objs_list, in_core_obj);
1414 in_core_obj = tmp_incore_obj;
1415 } else {
1416 in_core_obj = in_core_obj->next;
1417 }
1418 }
1419
1420 /*
1421 * At this point, if there's still anything on the on_disk_list, they
1422 * are all newly added objects since in-core list last loaded.
1423 * include all of them into the in-core list
1424 */
1425 next_on_disk = on_disk_list;
1426 while (next_on_disk) {
1427 new_objp = calloc(1, sizeof (soft_object_t));
1428 if (new_objp == NULL) {
1429 rv = CKR_HOST_MEMORY;
1430 goto cleanup;
1431 }
1432
1433 /* Convert the keystore format to memory format */
1434 rv = soft_keystore_unpack_obj(new_objp, next_on_disk);
1435 if (rv != CKR_OK) {
1436 soft_cleanup_object(new_objp);
1437 free(new_objp);
1438 goto cleanup;
1439 }
1440
1441 insert_into_list(&added_objs_list, &end_added_objs_list,
1442 new_objp);
1443
1444 /* free the on_disk object */
1445 tmp_on_disk = next_on_disk;
1446 next_on_disk = tmp_on_disk->next;
1447 free(tmp_on_disk->buf);
1448 free(tmp_on_disk);
1449 }
1450
1451 if (rv == CKR_OK) {
1452 (void) pthread_mutex_lock(&soft_giant_mutex);
1453 soft_slot.ks_version = on_disk_ks_version;
1454 (void) pthread_mutex_unlock(&soft_giant_mutex);
1455
1456 /* add the new objects into in-core list */
1457 insert_list_into_list(&(soft_slot.token_object_list),
1458 added_objs_list, end_added_objs_list);
1459
1460 /* add modified objects back into the in-core list */
1461 insert_list_into_list(&(soft_slot.token_object_list),
1462 mod_objs_list, end_mod_objs_list);
1463
1464 /* actually remove deleted objs, and copy of modified objs */
1465 delete_all_objs_in_list(copy_of_mod_objs_list);
1466 delete_all_objs_in_list(del_objs_list);
1467 }
1468
1469 return (rv);
1470
1471 cleanup:
1472 next_on_disk = on_disk_list;
1473 while (next_on_disk) {
1474 tmp_on_disk = next_on_disk;
1475 next_on_disk = tmp_on_disk->next;
1476 free(tmp_on_disk->buf);
1477 free(tmp_on_disk);
1478 }
1479
1480 /*
1481 * restore the in-core list back to the original state by adding
1482 * copy of original objects and deleted objects back to list
1483 */
1484 insert_list_into_list(&(soft_slot.token_object_list),
1485 del_objs_list, end_del_objs_list);
1486 insert_list_into_list(&(soft_slot.token_object_list),
1487 copy_of_mod_objs_list, end_copy_of_mod_objs_list);
1488
1489 /*
1490 * remove the modified objects, and newly objects list
1491 */
1492 delete_all_objs_in_list(mod_objs_list);
1493 delete_all_objs_in_list(added_objs_list);
1494 return (rv);
1495 }
1496
1497 CK_RV
dup_bigint_attr(biginteger_t * bi,CK_BYTE * buf,CK_ULONG buflen)1498 dup_bigint_attr(biginteger_t *bi, CK_BYTE *buf, CK_ULONG buflen)
1499 {
1500 bi->big_value_len = buflen;
1501 if ((bi->big_value = malloc(buflen)) == NULL) {
1502 return (CKR_HOST_MEMORY);
1503 }
1504 (void) memcpy(bi->big_value, buf, buflen);
1505 return (CKR_OK);
1506 }
1507