Merge commit '06307114472bd8aad5ff18ccdb8e25f128ae6652'
[unleashed.git] / usr / src / lib / pkcs11 / pkcs11_softtoken / common / softObject.c
blobd5aae8091084dac00b30dab1bf43881a09aa6658
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <pthread.h>
27 #include <stdlib.h>
28 #include <security/cryptoki.h>
29 #include "softGlobal.h"
30 #include "softObject.h"
31 #include "softSession.h"
32 #include "softKeystore.h"
33 #include "softKeystoreUtil.h"
36 CK_RV
37 C_CreateObject(CK_SESSION_HANDLE hSession,
38 CK_ATTRIBUTE_PTR pTemplate,
39 CK_ULONG ulCount,
40 CK_OBJECT_HANDLE_PTR phObject)
43 CK_RV rv;
44 soft_session_t *session_p;
45 boolean_t lock_held = B_FALSE;
47 if (!softtoken_initialized)
48 return (CKR_CRYPTOKI_NOT_INITIALIZED);
51 * Obtain the session pointer. Also, increment the session
52 * reference count.
54 rv = handle2session(hSession, &session_p);
55 if (rv != CKR_OK)
56 return (rv);
58 if ((pTemplate == NULL) || (ulCount == 0) ||
59 (phObject == NULL)) {
60 rv = CKR_ARGUMENTS_BAD;
61 goto clean_exit;
64 /* Create a new object. */
65 rv = soft_add_object(pTemplate, ulCount, phObject, session_p);
67 clean_exit:
69 * Decrement the session reference count.
70 * We do not hold the session lock.
72 SES_REFRELE(session_p, lock_held);
73 return (rv);
76 CK_RV
77 C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
78 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
79 CK_OBJECT_HANDLE_PTR phNewObject)
82 CK_RV rv;
83 soft_session_t *session_p;
84 boolean_t lock_held = B_FALSE;
85 soft_object_t *old_object, *new_object = NULL;
86 ulong_t i;
88 if (!softtoken_initialized)
89 return (CKR_CRYPTOKI_NOT_INITIALIZED);
92 * Obtain the session pointer. Also, increment the session
93 * reference count.
95 rv = handle2session(hSession, &session_p);
96 if (rv != CKR_OK)
97 return (rv);
99 /* Check arguments */
100 if (((ulCount > 0) && (pTemplate == NULL)) ||
101 (phNewObject == NULL)) {
102 rv = CKR_ARGUMENTS_BAD;
103 goto clean_exit;
106 /* Obtain the object pointer. */
107 HANDLE2OBJECT(hObject, old_object, rv);
108 if (rv != CKR_OK) {
109 goto clean_exit;
113 * Copy the old object to a new object.
114 * The 3rd argument with SOFT_COPY_OBJ value indicates that
115 * everything in the object will be duplicated for C_CopyObject.
116 * The 4th argument has the session pointer that will be
117 * saved in the new copy of the session object.
119 (void) pthread_mutex_lock(&old_object->object_mutex);
120 rv = soft_copy_object(old_object, &new_object, SOFT_COPY_OBJECT,
121 session_p);
123 if ((rv != CKR_OK) || (new_object == NULL)) {
124 /* Most likely we ran out of space. */
125 (void) pthread_mutex_unlock(&old_object->object_mutex);
126 goto clean_exit1;
129 /* No need to hold the lock on the old object. */
130 (void) pthread_mutex_unlock(&old_object->object_mutex);
132 /* Modifiy the objects if requested */
133 for (i = 0; i < ulCount; i++) {
134 /* Set the requested attribute into the new object. */
135 rv = soft_set_attribute(new_object, &pTemplate[i], B_TRUE);
136 if (rv != CKR_OK) {
137 goto fail;
141 rv = soft_pin_expired_check(new_object);
142 if (rv != CKR_OK) {
143 goto fail;
147 * Does the new object violate the creation rule or access rule?
149 rv = soft_object_write_access_check(session_p, new_object);
150 if (rv != CKR_OK) {
151 goto fail;
155 * If the new object is a token object, it will be added
156 * to token object list and write to disk.
158 if (IS_TOKEN_OBJECT(new_object)) {
159 new_object->version = 1;
161 * Write to the keystore file.
163 rv = soft_put_object_to_keystore(new_object);
164 if (rv != CKR_OK) {
165 goto fail;
168 new_object->session_handle = (CK_SESSION_HANDLE)NULL;
170 * Add the newly created token object to the global
171 * token object list in the slot struct.
173 soft_add_token_object_to_slot(new_object);
174 OBJ_REFRELE(old_object);
175 SES_REFRELE(session_p, lock_held);
176 *phNewObject = (CK_ULONG)new_object;
178 return (CKR_OK);
181 /* Insert new object into this session's object list */
182 soft_add_object_to_session(new_object, session_p);
185 * Decrement the session reference count.
186 * We do not hold the session lock.
188 OBJ_REFRELE(old_object);
189 SES_REFRELE(session_p, lock_held);
191 /* set handle of the new object */
192 *phNewObject = (CK_ULONG)new_object;
194 return (rv);
196 fail:
197 soft_cleanup_object(new_object);
198 free(new_object);
200 clean_exit1:
201 OBJ_REFRELE(old_object);
202 clean_exit:
203 SES_REFRELE(session_p, lock_held);
204 return (rv);
207 CK_RV
208 C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
211 CK_RV rv;
212 soft_object_t *object_p;
213 soft_session_t *session_p = (soft_session_t *)(hSession);
214 boolean_t lock_held = B_FALSE;
215 CK_SESSION_HANDLE creating_session;
218 if (!softtoken_initialized)
219 return (CKR_CRYPTOKI_NOT_INITIALIZED);
222 * The reason that we don't call handle2session is because
223 * the argument hSession may not be the creating_session of
224 * the object to be destroyed, and we want to avoid the lock
225 * contention. The handle2session will be called later for
226 * the creating_session.
228 if ((session_p == NULL) ||
229 (session_p->magic_marker != SOFTTOKEN_SESSION_MAGIC)) {
230 return (CKR_SESSION_HANDLE_INVALID);
233 /* Obtain the object pointer. */
234 HANDLE2OBJECT_DESTROY(hObject, object_p, rv);
235 if (rv != CKR_OK) {
236 return (rv);
239 /* Obtain the session handle which object belongs to. */
240 creating_session = object_p->session_handle;
242 if (creating_session == 0) {
244 * This is a token object to be deleted.
245 * For token object, there is no creating session concept,
246 * therefore, creating_session is always NULL.
248 rv = soft_pin_expired_check(object_p);
249 if (rv != CKR_OK) {
250 return (rv);
253 /* Obtain the session pointer just for validity check. */
254 rv = handle2session(hSession, &session_p);
255 if (rv != CKR_OK) {
256 return (rv);
259 rv = soft_object_write_access_check(session_p, object_p);
260 if (rv != CKR_OK) {
261 SES_REFRELE(session_p, lock_held);
262 return (rv);
266 * Set OBJECT_IS_DELETING flag so any access to this
267 * object will be rejected.
269 (void) pthread_mutex_lock(&object_p->object_mutex);
270 if (object_p->obj_delete_sync & OBJECT_IS_DELETING) {
271 (void) pthread_mutex_unlock(&object_p->object_mutex);
272 SES_REFRELE(session_p, lock_held);
273 return (CKR_OBJECT_HANDLE_INVALID);
275 object_p->obj_delete_sync |= OBJECT_IS_DELETING;
276 (void) pthread_mutex_unlock(&object_p->object_mutex);
277 SES_REFRELE(session_p, lock_held);
280 * Delete a token object by calling soft_delete_token_object()
281 * with the second argument B_TRUE indicating to delete the
282 * object from keystore and the third argument B_FALSE
283 * indicating that the caller does not hold the slot mutex.
285 soft_delete_token_object(object_p, B_TRUE, B_FALSE);
286 return (CKR_OK);
290 * Obtain the session pointer. Also, increment the session
291 * reference count.
293 rv = handle2session(creating_session, &session_p);
294 if (rv != CKR_OK) {
295 return (rv);
299 * Set OBJECT_IS_DELETING flag so any access to this
300 * object will be rejected.
302 (void) pthread_mutex_lock(&object_p->object_mutex);
303 if (object_p->obj_delete_sync & OBJECT_IS_DELETING) {
304 (void) pthread_mutex_unlock(&object_p->object_mutex);
305 SES_REFRELE(session_p, lock_held);
306 return (CKR_OBJECT_HANDLE_INVALID);
308 object_p->obj_delete_sync |= OBJECT_IS_DELETING;
309 (void) pthread_mutex_unlock(&object_p->object_mutex);
312 * Delete an object by calling soft_delete_object()
313 * with a FALSE boolean argument indicating that
314 * the caller does not hold the session lock.
316 soft_delete_object(session_p, object_p, B_FALSE, B_FALSE);
319 * Decrement the session reference count.
320 * We do not hold the session lock.
322 SES_REFRELE(session_p, lock_held);
324 return (rv);
328 CK_RV
329 C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
330 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
333 CK_RV rv = CKR_OK, rv1 = CKR_OK;
334 soft_object_t *object_p;
335 soft_session_t *session_p;
336 boolean_t lock_held = B_FALSE;
337 ulong_t i;
339 if (!softtoken_initialized)
340 return (CKR_CRYPTOKI_NOT_INITIALIZED);
343 * Obtain the session pointer. Also, increment the session
344 * reference count.
346 rv = handle2session(hSession, &session_p);
347 if (rv != CKR_OK)
348 return (rv);
350 if ((pTemplate == NULL) || (ulCount == 0)) {
352 * Decrement the session reference count.
353 * We do not hold the session lock.
355 SES_REFRELE(session_p, lock_held);
356 return (CKR_ARGUMENTS_BAD);
359 /* Obtain the object pointer. */
360 HANDLE2OBJECT(hObject, object_p, rv);
361 if (rv != CKR_OK) {
363 * Decrement the session reference count.
364 * We do not hold the session lock.
366 SES_REFRELE(session_p, lock_held);
367 return (rv);
370 if (IS_TOKEN_OBJECT(object_p)) {
372 rv = soft_keystore_load_latest_object(object_p);
373 if (rv != CKR_OK) {
374 OBJ_REFRELE(object_p);
375 SES_REFRELE(session_p, lock_held);
376 return (rv);
380 /* Acquire the lock on the object. */
381 (void) pthread_mutex_lock(&object_p->object_mutex);
383 for (i = 0; i < ulCount; i++) {
385 * Get the value of each attribute in the template.
386 * (We must process EVERY attribute in the template.)
388 rv = soft_get_attribute(object_p, &pTemplate[i]);
389 if (rv != CKR_OK)
390 /* At least we catch some type of error. */
391 rv1 = rv;
394 /* Release the object lock */
395 (void) pthread_mutex_unlock(&object_p->object_mutex);
398 * Decrement the session reference count.
399 * We do not hold the session lock.
401 OBJ_REFRELE(object_p);
402 SES_REFRELE(session_p, lock_held);
404 rv = rv1;
405 return (rv);
409 CK_RV
410 C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
411 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
413 CK_RV rv = CKR_OK;
414 soft_object_t *object_p;
415 soft_object_t *new_object = NULL;
416 soft_session_t *session_p;
417 boolean_t lock_held = B_FALSE;
418 ulong_t i;
420 if (!softtoken_initialized)
421 return (CKR_CRYPTOKI_NOT_INITIALIZED);
424 * Obtain the session pointer. Also, increment the session
425 * reference count.
427 rv = handle2session(hSession, &session_p);
428 if (rv != CKR_OK)
429 return (rv);
431 if ((pTemplate == NULL) || (ulCount == 0)) {
433 * Decrement the session reference count.
434 * We do not hold the session lock.
436 SES_REFRELE(session_p, lock_held);
437 return (CKR_ARGUMENTS_BAD);
440 /* Obtain the object pointer. */
441 HANDLE2OBJECT(hObject, object_p, rv);
442 if (rv != CKR_OK) {
444 * Decrement the session reference count.
445 * We do not hold the session lock.
447 SES_REFRELE(session_p, lock_held);
448 return (rv);
451 if (object_p->bool_attr_mask & NOT_MODIFIABLE_BOOL_ON) {
452 rv = CKR_ATTRIBUTE_READ_ONLY;
453 goto fail_1;
457 * Start working on the object, so we need to set the write lock so that
458 * no one can write to it but still can read it.
460 if (IS_TOKEN_OBJECT(object_p)) {
461 rv = soft_keystore_load_latest_object(object_p);
462 if (rv != CKR_OK) {
463 goto fail_1;
468 * Copy the old object to a new object. We work on the copied
469 * version because in case of error we still keep the old one
470 * intact.
471 * The 3rd argument with SOFT_SET_ATTR_VALUE value indicates that
472 * not everything will be duplicated for C_SetAttributeValue.
473 * Information not duplicated are those attributes that are not
474 * modifiable.
476 (void) pthread_mutex_lock(&object_p->object_mutex);
477 rv = soft_copy_object(object_p, &new_object, SOFT_SET_ATTR_VALUE, NULL);
479 if ((rv != CKR_OK) || (new_object == NULL)) {
480 /* Most likely we ran out of space. */
481 (void) pthread_mutex_unlock(&object_p->object_mutex);
483 * Decrement the session reference count.
484 * We do not hold the session lock.
486 goto fail_1;
490 * No need to hold the lock on the old object, because we
491 * will be working on the new scratch object.
493 (void) pthread_mutex_unlock(&object_p->object_mutex);
495 rv = soft_object_write_access_check(session_p, new_object);
496 if (rv != CKR_OK) {
497 goto fail;
500 for (i = 0; i < ulCount; i++) {
501 /* Set the requested attribute into the new object. */
502 rv = soft_set_attribute(new_object, &pTemplate[i], B_FALSE);
504 if (rv != CKR_OK) {
505 goto fail;
510 * We've successfully set all the requested attributes.
511 * Merge the new object with the old object, then destory
512 * the new one. The reason to do the merging is because we
513 * have to keep the original object handle (address of object).
515 (void) pthread_mutex_lock(&object_p->object_mutex);
517 soft_merge_object(object_p, new_object);
520 * The object has been modified, so we write it back to keystore.
522 if (IS_TOKEN_OBJECT(object_p)) {
523 object_p->version++;
524 rv = soft_modify_object_to_keystore(object_p);
527 (void) pthread_mutex_unlock(&object_p->object_mutex);
528 free(new_object);
531 * Decrement the session reference count.
532 * We do not hold the session lock.
534 OBJ_REFRELE(object_p);
535 SES_REFRELE(session_p, lock_held);
536 return (rv);
538 fail:
539 soft_cleanup_object(new_object);
540 free(new_object);
542 fail_1:
543 OBJ_REFRELE(object_p);
544 SES_REFRELE(session_p, lock_held);
546 return (rv);
549 /*ARGSUSED*/
550 CK_RV
551 C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
552 CK_ULONG_PTR pulSize)
554 if (!softtoken_initialized)
555 return (CKR_CRYPTOKI_NOT_INITIALIZED);
557 return (CKR_FUNCTION_NOT_SUPPORTED);
560 CK_RV
561 C_FindObjectsInit(CK_SESSION_HANDLE sh, CK_ATTRIBUTE_PTR pTemplate,
562 CK_ULONG ulCount)
565 CK_RV rv;
566 soft_session_t *session_p;
567 boolean_t lock_held = B_TRUE;
569 if (!softtoken_initialized)
570 return (CKR_CRYPTOKI_NOT_INITIALIZED);
573 * Obtain the session pointer. Also, increment the session
574 * reference count.
576 rv = handle2session(sh, &session_p);
577 if (rv != CKR_OK)
578 return (rv);
580 /* Check the arguments */
581 if ((ulCount > 0) && (pTemplate == NULL)) {
582 /* decrement the session count, we do not hold the lock */
583 lock_held = B_FALSE;
584 SES_REFRELE(session_p, lock_held);
585 return (CKR_ARGUMENTS_BAD);
588 /* Acquire the session lock */
589 (void) pthread_mutex_lock(&session_p->session_mutex);
591 /* Check to see if find operation is already active */
592 if (session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE) {
593 /* decrement the session count, and unlock the mutex */
594 SES_REFRELE(session_p, lock_held);
595 return (CKR_OPERATION_ACTIVE);
596 } else {
598 * This active flag will remain ON until application calls
599 * C_FindObjectsFinal.
601 session_p->find_objects.flags = CRYPTO_OPERATION_ACTIVE;
604 (void) pthread_mutex_unlock(&session_p->session_mutex);
606 rv = soft_find_objects_init(session_p, pTemplate, ulCount);
608 if (rv != CKR_OK) {
609 (void) pthread_mutex_lock(&session_p->session_mutex);
610 session_p->find_objects.flags = 0;
611 (void) pthread_mutex_unlock(&session_p->session_mutex);
614 /* decrement the session count, and unlock the mutex */
615 lock_held = B_FALSE;
616 SES_REFRELE(session_p, lock_held);
617 return (rv);
620 CK_RV
621 C_FindObjects(CK_SESSION_HANDLE sh,
622 CK_OBJECT_HANDLE_PTR phObject,
623 CK_ULONG ulMaxObjectCount,
624 CK_ULONG_PTR pulObjectCount)
626 soft_session_t *session_p;
627 CK_RV rv = CKR_OK;
628 boolean_t lock_held = B_TRUE;
630 if (!softtoken_initialized)
631 return (CKR_CRYPTOKI_NOT_INITIALIZED);
634 * Obtain the session pointer. Also, increment the session
635 * reference count.
637 rv = handle2session(sh, &session_p);
638 if (rv != CKR_OK)
639 return (rv);
641 /* check for invalid arguments */
642 if (((phObject == NULL) && (ulMaxObjectCount != 0)) ||
643 (pulObjectCount == NULL)) {
644 /* decrement the session count, we do not hold the lock */
645 lock_held = B_FALSE;
646 SES_REFRELE(session_p, lock_held);
647 return (CKR_ARGUMENTS_BAD);
650 if (ulMaxObjectCount == 0) {
651 /* don't need to do anything, just return */
652 *pulObjectCount = 0;
653 /* decrement the session count, we do not hold the lock */
654 lock_held = B_FALSE;
655 SES_REFRELE(session_p, lock_held);
656 return (CKR_OK);
659 /* Acquire the session lock */
660 (void) pthread_mutex_lock(&session_p->session_mutex);
662 /* Check to see if find operation is active */
663 if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
664 SES_REFRELE(session_p, lock_held);
665 return (CKR_OPERATION_NOT_INITIALIZED);
668 soft_find_objects(session_p, phObject, ulMaxObjectCount,
669 pulObjectCount);
671 /* decrement the session count, and release the lock */
672 SES_REFRELE(session_p, lock_held);
673 return (rv);
676 CK_RV
677 C_FindObjectsFinal(CK_SESSION_HANDLE sh)
679 soft_session_t *session_p;
680 CK_RV rv;
681 boolean_t lock_held = B_TRUE;
683 if (!softtoken_initialized)
684 return (CKR_CRYPTOKI_NOT_INITIALIZED);
687 * Obtain the session pointer. Also, increment the session
688 * reference count.
690 rv = handle2session(sh, &session_p);
691 if (rv != CKR_OK)
692 return (rv);
694 /* Acquire the session lock */
695 (void) pthread_mutex_lock(&session_p->session_mutex);
697 /* Check to see if find operation is active */
698 if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
699 SES_REFRELE(session_p, lock_held);
700 return (CKR_OPERATION_NOT_INITIALIZED);
703 soft_find_objects_final(session_p);
705 /* decrement the session count, and release the lock */
706 SES_REFRELE(session_p, lock_held);
707 return (rv);