998 obsolete DMA driver interfaces should be removed
[illumos-gate.git] / usr / src / lib / pkcs11 / pkcs11_kms / common / kmsObject.c
blob2ddd76fab9d6e80305c57f256202b5c2d99b3dfe
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
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
27 #include <pthread.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <security/cryptoki.h>
33 #include "kmsGlobal.h"
34 #include "kmsObject.h"
35 #include "kmsSession.h"
37 CK_RV
38 C_CreateObject(CK_SESSION_HANDLE hSession,
39 CK_ATTRIBUTE_PTR pTemplate,
40 CK_ULONG ulCount,
41 CK_OBJECT_HANDLE_PTR phObject)
44 CK_RV rv;
45 kms_session_t *session_p;
46 boolean_t ses_lock_held = B_FALSE;
48 if (!kms_initialized)
49 return (CKR_CRYPTOKI_NOT_INITIALIZED);
51 if ((pTemplate == NULL) || (ulCount == 0) ||
52 (phObject == NULL)) {
53 return (CKR_ARGUMENTS_BAD);
57 * Obtain the session pointer. Also, increment the session
58 * reference count.
60 rv = handle2session(hSession, &session_p);
61 if (rv != CKR_OK)
62 return (rv);
64 /* Create a new object. */
65 rv = kms_add_object(pTemplate, ulCount, phObject, session_p);
68 * Decrement the session reference count.
69 * We do not hold the session lock.
71 REFRELE(session_p, ses_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 kms_session_t *session_p;
84 boolean_t ses_lock_held = B_FALSE;
85 kms_object_t *old_object;
86 kms_object_t *new_object = NULL;
87 int i;
89 if (!kms_initialized)
90 return (CKR_CRYPTOKI_NOT_INITIALIZED);
92 /* Check arguments */
93 if (((ulCount > 0) && (pTemplate == NULL)) ||
94 (phNewObject == NULL)) {
95 return (CKR_ARGUMENTS_BAD);
99 * Obtain the session pointer. Also, increment the session
100 * reference count.
102 rv = handle2session(hSession, &session_p);
103 if (rv != CKR_OK)
104 return (rv);
106 /* Obtain the object pointer. */
107 HANDLE2OBJECT(hObject, old_object, rv);
108 if (rv != CKR_OK) {
110 * Decrement the session reference count.
111 * We do not hold the session lock.
113 REFRELE(session_p, ses_lock_held);
114 return (rv);
117 (void) pthread_mutex_lock(&old_object->object_mutex);
119 if (old_object->is_lib_obj) {
121 * Copy the old object to a new object.
122 * The 3rd argument with TRUE value indicates that
123 * everything in the object will be duplicated.
125 rv = kms_copy_object(old_object, &new_object, B_TRUE,
126 session_p);
127 (void) pthread_mutex_unlock(&old_object->object_mutex);
128 if ((rv != CKR_OK) || (new_object == NULL)) {
130 * Most likely we ran out of space.
131 * Decrement the session reference count.
132 * We do not hold the session lock.
134 OBJ_REFRELE(old_object);
135 REFRELE(session_p, ses_lock_held);
136 return (rv);
139 new_object->is_lib_obj = B_TRUE;
141 /* Modify the object attribute if requested */
142 for (i = 0; i < ulCount; i++) {
143 /* Set the requested attribute into the new object. */
144 rv = kms_set_attribute(new_object, &pTemplate[i],
145 B_TRUE);
147 if (rv != CKR_OK) {
148 kms_cleanup_object(new_object);
149 OBJ_REFRELE(old_object);
150 REFRELE(session_p, ses_lock_held);
151 return (rv);
155 /* Insert the new object into this session's object list. */
156 kms_add_object_to_session(new_object, session_p);
159 * Decrement the session reference count.
160 * We do not hold the session lock.
162 OBJ_REFRELE(old_object);
163 REFRELE(session_p, ses_lock_held);
165 /* set handle of the new object */
166 *phNewObject = (CK_ULONG)new_object;
170 return (rv);
172 failed_cleanup:
173 if (new_object != NULL) {
174 (void) kms_free_object(new_object);
177 OBJ_REFRELE(old_object);
178 REFRELE(session_p, ses_lock_held);
179 return (rv);
182 CK_RV
183 C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
185 CK_RV rv;
186 kms_object_t *object_p;
187 kms_session_t *session_p = (kms_session_t *)(hSession);
188 kms_slot_t *pslot;
189 boolean_t ses_lock_held = B_FALSE;
190 CK_SESSION_HANDLE creating_session;
192 if (!kms_initialized)
193 return (CKR_CRYPTOKI_NOT_INITIALIZED);
196 * The reason that we don't call handle2session is because
197 * the argument hSession may not be the creating_session of
198 * the object to be destroyed, and we want to avoid the lock
199 * contention. The handle2session will be called later for
200 * the creating_session.
202 if ((session_p == NULL) ||
203 (session_p->magic_marker != KMSTOKEN_SESSION_MAGIC)) {
204 return (CKR_SESSION_HANDLE_INVALID);
206 /* Obtain the object pointer without incrementing reference count. */
207 HANDLE2OBJECT_DESTROY(hObject, object_p, rv);
208 if (rv != CKR_OK) {
209 return (rv);
212 /* Only session objects can be destroyed at a read-only session. */
213 if ((session_p->ses_RO) &&
214 (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
215 return (CKR_SESSION_READ_ONLY);
220 * If the object is a session object, obtain the session handle
221 * which object belongs to. For a token object, we will use the
222 * session handle from the caller, because the session used to
223 * create the token object may no longer exist.
225 if (!(object_p->bool_attr_mask & TOKEN_BOOL_ON))
226 creating_session = object_p->session_handle;
227 else
228 creating_session = hSession;
230 rv = handle2session(creating_session, &session_p);
231 if (rv != CKR_OK) {
232 return (rv);
236 * Set OBJECT_IS_DELETING flag so any access to this
237 * object will be rejected.
239 (void) pthread_mutex_lock(&object_p->object_mutex);
240 if (object_p->obj_delete_sync & OBJECT_IS_DELETING) {
241 (void) pthread_mutex_unlock(&object_p->object_mutex);
242 REFRELE(session_p, ses_lock_held);
243 return (CKR_OBJECT_HANDLE_INVALID);
245 object_p->obj_delete_sync |= OBJECT_IS_DELETING;
246 (void) pthread_mutex_unlock(&object_p->object_mutex);
248 if (object_p->bool_attr_mask & TOKEN_BOOL_ON) {
250 * The first FALSE boolean argument indicates that the caller
251 * does not hold the slot lock. The second FALSE boolean
252 * argument indicates that the caller wants to clean up the
253 * object in the HW provider also.
255 pslot = get_slotinfo();
256 rv = kms_delete_token_object(pslot, session_p, object_p,
257 B_FALSE, B_FALSE);
258 } else {
260 * The first FALSE boolean argument indicates that the caller
261 * does not hold the session lock. The second FALSE boolean
262 * argument indicates that the caller wants to clean the object
263 * in the HW provider also.
265 rv = kms_delete_object(session_p, object_p, B_FALSE,
266 B_FALSE);
269 * Decrement the session reference count.
270 * We do not hold the session lock.
272 REFRELE(session_p, ses_lock_held);
273 return (rv);
276 CK_RV
277 C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
278 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
281 CK_RV rv = CKR_OK, rv1 = CKR_OK;
282 kms_object_t *object_p;
283 kms_session_t *session_p;
284 boolean_t ses_lock_held = B_FALSE;
285 int i;
287 if (!kms_initialized)
288 return (CKR_CRYPTOKI_NOT_INITIALIZED);
290 if ((pTemplate == NULL) || (ulCount == 0))
291 return (CKR_ARGUMENTS_BAD);
294 * Obtain the session pointer. Also, increment the session
295 * reference count.
297 rv = handle2session(hSession, &session_p);
298 if (rv != CKR_OK)
299 return (rv);
301 /* Obtain the object pointer. */
302 HANDLE2OBJECT(hObject, object_p, rv);
303 if (rv != CKR_OK) {
305 * Decrement the session reference count.
306 * We do not hold the session lock.
308 REFRELE(session_p, ses_lock_held);
309 return (rv);
312 /* Acquire the lock on the object. */
313 (void) pthread_mutex_lock(&object_p->object_mutex);
316 * The object was created in the library. The library
317 * contains the value information of each attribute.
319 for (i = 0; i < ulCount; i++) {
321 * Get the value of each attribute in the template.
322 * (We must process EVERY attribute in the template.)
324 rv = kms_get_attribute(object_p, &pTemplate[i]);
325 if (rv != CKR_OK)
326 rv1 = rv;
328 (void) pthread_mutex_unlock(&object_p->object_mutex);
330 clean_exit:
332 * Decrement the session reference count.
333 * We do not hold the session lock.
335 OBJ_REFRELE(object_p);
336 REFRELE(session_p, ses_lock_held);
337 rv = rv1;
338 return (rv);
341 CK_RV
342 C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
343 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
345 CK_RV rv = CKR_OK;
346 kms_object_t *object_p;
347 kms_object_t *new_object = NULL;
348 kms_session_t *session_p;
349 boolean_t ses_lock_held = B_FALSE;
350 int i;
352 if (!kms_initialized)
353 return (CKR_CRYPTOKI_NOT_INITIALIZED);
355 if ((pTemplate == NULL) || (ulCount == 0))
356 return (CKR_ARGUMENTS_BAD);
359 * Obtain the session pointer. Also, increment the session
360 * reference count.
362 rv = handle2session(hSession, &session_p);
363 if (rv != CKR_OK)
364 return (rv);
366 /* Obtain the object pointer. */
367 HANDLE2OBJECT(hObject, object_p, rv);
368 if (rv != CKR_OK) {
370 * Decrement the session reference count.
371 * We do not hold the session lock.
373 REFRELE(session_p, ses_lock_held);
374 return (rv);
377 /* lock the object */
378 (void) pthread_mutex_lock(&object_p->object_mutex);
381 * If the object was created in the HW provider, changing its
382 * attributes' values need to be done in the provider too.
384 if (!object_p->is_lib_obj) {
386 /* Cannot modify a token object with a READ-ONLY session */
387 if (session_p->ses_RO &&
388 (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
389 (void) pthread_mutex_unlock(&object_p->object_mutex);
390 rv = CKR_SESSION_READ_ONLY;
391 goto clean_exit;
396 * if we come here, the object must have been created in the
397 * library. The work will be done completely in the library.
399 * Copy the old object to a new object. We work on the copied
400 * version because in case of error we still keep the old one
401 * intact.
403 rv = kms_copy_object(object_p, &new_object, B_FALSE, NULL);
404 (void) pthread_mutex_unlock(&object_p->object_mutex);
405 if ((rv != CKR_OK) || (new_object == NULL)) {
407 * Most likely we ran out of space.
408 * Decrement the session reference count.
409 * We do not hold the session lock.
411 goto clean_exit;
414 for (i = 0; i < ulCount; i++) {
415 /* Set the requested attribute into the new object. */
416 rv = kms_set_attribute(new_object, &pTemplate[i], B_FALSE);
418 if (rv != CKR_OK) {
419 kms_cleanup_object(new_object);
420 goto clean_exit;
425 * We've successfully set all the requested attributes.
426 * Merge the new object with the old object, then destory
427 * the new one. The reason to do the merging is because we
428 * have to keep the original object handle (address of object).
430 (void) pthread_mutex_lock(&object_p->object_mutex);
431 kms_merge_object(object_p, new_object);
432 (void) pthread_mutex_unlock(&object_p->object_mutex);
434 clean_exit:
435 if (new_object != NULL)
436 (void) kms_free_object(new_object);
439 * Decrement the session reference count.
440 * We do not hold the session lock.
442 OBJ_REFRELE(object_p);
443 REFRELE(session_p, ses_lock_held);
445 return (rv);
448 CK_RV
449 C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
450 CK_ULONG_PTR pulSize)
453 CK_RV rv = CKR_OK;
454 kms_object_t *object_p;
455 kms_session_t *session_p;
456 boolean_t ses_lock_held = B_FALSE;
458 if (!kms_initialized)
459 return (CKR_CRYPTOKI_NOT_INITIALIZED);
461 /* Check if pulSize is valid */
462 if (pulSize == NULL) {
463 return (CKR_ARGUMENTS_BAD);
467 * Obtain the session pointer. Also, increment the session
468 * reference count.
470 rv = handle2session(hSession, &session_p);
471 if (rv != CKR_OK)
472 return (rv);
474 /* Obtain the object pointer. */
475 HANDLE2OBJECT(hObject, object_p, rv);
476 if (rv != CKR_OK) {
478 * Decrement the session reference count.
479 * We do not hold the session lock.
481 REFRELE(session_p, ses_lock_held);
482 return (rv);
485 /* Acquire the lock on the object. */
486 (void) pthread_mutex_lock(&object_p->object_mutex);
488 rv = kms_get_object_size(object_p, pulSize);
490 (void) pthread_mutex_unlock(&object_p->object_mutex);
493 * Decrement the session reference count.
494 * We do not hold the session lock.
496 OBJ_REFRELE(object_p);
497 REFRELE(session_p, ses_lock_held);
498 return (rv);
501 CK_RV
502 C_FindObjectsInit(CK_SESSION_HANDLE sh, CK_ATTRIBUTE_PTR pTemplate,
503 CK_ULONG ulCount)
505 CK_RV rv;
506 kms_session_t *session_p;
507 boolean_t ses_lock_held = B_FALSE;
509 if (!kms_initialized)
510 return (CKR_CRYPTOKI_NOT_INITIALIZED);
512 /* Check the arguments */
513 if ((ulCount > 0) && (pTemplate == NULL)) {
514 return (CKR_ARGUMENTS_BAD);
518 * Obtain the session pointer. Also, increment the session
519 * reference count.
521 rv = handle2session(sh, &session_p);
522 if (rv != CKR_OK)
523 return (rv);
525 /* Acquire the session lock */
526 (void) pthread_mutex_lock(&session_p->session_mutex);
527 ses_lock_held = B_TRUE;
529 /* Check to see if find operation is already active */
530 if (session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE) {
531 /* decrement the session count, and unlock the mutex */
532 REFRELE(session_p, ses_lock_held);
533 return (CKR_OPERATION_ACTIVE);
534 } else {
536 * This active flag will remain ON until application calls
537 * C_FindObjectsFinal.
539 session_p->find_objects.flags = CRYPTO_OPERATION_ACTIVE;
541 (void) pthread_mutex_unlock(&session_p->session_mutex);
544 * If the KMS provider supports object creation, we call the
545 * CRYPTO_OBJECT_FIND_INIT to initialize object finding.
546 * Otherwise, all the objects are created in the library and we
547 * do the find objects solely in the library.
549 rv = kms_find_objects_init(session_p, pTemplate, ulCount);
550 if (rv != CKR_OK) {
551 (void) pthread_mutex_lock(&session_p->session_mutex);
552 session_p->find_objects.flags = 0;
553 (void) pthread_mutex_unlock(&session_p->session_mutex);
555 /* decrement the session count, and unlock the mutex */
556 REFRELE(session_p, ses_lock_held);
557 return (rv);
560 CK_RV
561 C_FindObjects(CK_SESSION_HANDLE sh, CK_OBJECT_HANDLE_PTR phObject,
562 CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
564 CK_RV rv = CKR_OK;
565 kms_slot_t *pslot = NULL;
566 kms_session_t *session_p;
567 boolean_t ses_lock_held = B_FALSE;
569 if (!kms_initialized)
570 return (CKR_CRYPTOKI_NOT_INITIALIZED);
572 /* check for invalid arguments */
573 if (((phObject == NULL) && (ulMaxObjectCount != 0)) ||
574 (pulObjectCount == NULL)) {
575 return (CKR_ARGUMENTS_BAD);
578 if (ulMaxObjectCount == 0) {
579 /* don't need to do anything, just return */
580 *pulObjectCount = 0;
581 return (CKR_OK);
585 * Obtain the session pointer. Also, increment the session
586 * reference count.
588 rv = handle2session(sh, &session_p);
589 if (rv != CKR_OK)
590 return (rv);
592 /* Acquire the slot lock */
593 pslot = get_slotinfo();
594 (void) pthread_mutex_lock(&pslot->sl_mutex);
596 /* Acquire the session lock */
597 (void) pthread_mutex_lock(&session_p->session_mutex);
598 ses_lock_held = B_TRUE;
600 /* Check to see if find operation is active */
601 if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
602 rv = CKR_OPERATION_NOT_INITIALIZED;
603 goto clean_exit;
607 * Similar to C_FindObjectInit(), if the KMS provider supports object
608 * creation, we need to find objects.
609 * Otherwise, all the objects are created in the library and we do
610 * the find objects solely in the library.
613 rv = kms_find_objects(session_p, phObject,
614 ulMaxObjectCount, pulObjectCount);
616 clean_exit:
617 /* decrement the session count, and release the session lock */
618 REFRELE(session_p, ses_lock_held);
620 /* release the slot lock */
621 if (pslot)
622 (void) pthread_mutex_unlock(&pslot->sl_mutex);
624 return (rv);
627 CK_RV
628 C_FindObjectsFinal(CK_SESSION_HANDLE sh)
630 kms_session_t *session_p;
631 CK_RV rv;
632 boolean_t ses_lock_held = B_FALSE;
634 if (!kms_initialized)
635 return (CKR_CRYPTOKI_NOT_INITIALIZED);
638 * Obtain the session pointer. Also, increment the session
639 * reference count.
641 rv = handle2session(sh, &session_p);
642 if (rv != CKR_OK)
643 return (rv);
645 /* Acquire the session lock */
646 (void) pthread_mutex_lock(&session_p->session_mutex);
647 ses_lock_held = B_TRUE;
649 /* Check to see if find operation is active */
650 if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
651 REFRELE(session_p, ses_lock_held);
652 return (CKR_OPERATION_NOT_INITIALIZED);
656 * Similar to C_FindObjectInit(), if the KMS provider supports object
657 * creation, we need to finalize the search on the KMS side.
659 kms_find_objects_final(session_p);
661 /* decrement the session count, and release the lock */
662 REFRELE(session_p, ses_lock_held);
663 return (rv);