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]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
32 #include <security/cryptoki.h>
33 #include "kmsGlobal.h"
34 #include "kmsObject.h"
35 #include "kmsSession.h"
38 C_CreateObject(CK_SESSION_HANDLE hSession
,
39 CK_ATTRIBUTE_PTR pTemplate
,
41 CK_OBJECT_HANDLE_PTR phObject
)
45 kms_session_t
*session_p
;
46 boolean_t ses_lock_held
= B_FALSE
;
49 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
51 if ((pTemplate
== NULL
) || (ulCount
== 0) ||
53 return (CKR_ARGUMENTS_BAD
);
57 * Obtain the session pointer. Also, increment the session
60 rv
= handle2session(hSession
, &session_p
);
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
);
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
)
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
;
90 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
93 if (((ulCount
> 0) && (pTemplate
== NULL
)) ||
94 (phNewObject
== NULL
)) {
95 return (CKR_ARGUMENTS_BAD
);
99 * Obtain the session pointer. Also, increment the session
102 rv
= handle2session(hSession
, &session_p
);
106 /* Obtain the object pointer. */
107 HANDLE2OBJECT(hObject
, old_object
, rv
);
110 * Decrement the session reference count.
111 * We do not hold the session lock.
113 REFRELE(session_p
, ses_lock_held
);
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
,
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
);
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
],
148 kms_cleanup_object(new_object
);
149 OBJ_REFRELE(old_object
);
150 REFRELE(session_p
, ses_lock_held
);
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
;
173 if (new_object
!= NULL
) {
174 (void) kms_free_object(new_object
);
177 OBJ_REFRELE(old_object
);
178 REFRELE(session_p
, ses_lock_held
);
183 C_DestroyObject(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
)
186 kms_object_t
*object_p
;
187 kms_session_t
*session_p
= (kms_session_t
*)(hSession
);
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
);
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
;
228 creating_session
= hSession
;
230 rv
= handle2session(creating_session
, &session_p
);
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
,
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
,
269 * Decrement the session reference count.
270 * We do not hold the session lock.
272 REFRELE(session_p
, ses_lock_held
);
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
;
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
297 rv
= handle2session(hSession
, &session_p
);
301 /* Obtain the object pointer. */
302 HANDLE2OBJECT(hObject
, object_p
, rv
);
305 * Decrement the session reference count.
306 * We do not hold the session lock.
308 REFRELE(session_p
, ses_lock_held
);
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
]);
328 (void) pthread_mutex_unlock(&object_p
->object_mutex
);
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
);
342 C_SetAttributeValue(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
,
343 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
)
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
;
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
362 rv
= handle2session(hSession
, &session_p
);
366 /* Obtain the object pointer. */
367 HANDLE2OBJECT(hObject
, object_p
, rv
);
370 * Decrement the session reference count.
371 * We do not hold the session lock.
373 REFRELE(session_p
, ses_lock_held
);
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
;
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
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.
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
);
419 kms_cleanup_object(new_object
);
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
);
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
);
449 C_GetObjectSize(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
,
450 CK_ULONG_PTR pulSize
)
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
470 rv
= handle2session(hSession
, &session_p
);
474 /* Obtain the object pointer. */
475 HANDLE2OBJECT(hObject
, object_p
, rv
);
478 * Decrement the session reference count.
479 * We do not hold the session lock.
481 REFRELE(session_p
, ses_lock_held
);
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
);
502 C_FindObjectsInit(CK_SESSION_HANDLE sh
, CK_ATTRIBUTE_PTR pTemplate
,
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
521 rv
= handle2session(sh
, &session_p
);
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
);
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
);
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
);
561 C_FindObjects(CK_SESSION_HANDLE sh
, CK_OBJECT_HANDLE_PTR phObject
,
562 CK_ULONG ulMaxObjectCount
, CK_ULONG_PTR pulObjectCount
)
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 */
585 * Obtain the session pointer. Also, increment the session
588 rv
= handle2session(sh
, &session_p
);
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
;
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
);
617 /* decrement the session count, and release the session lock */
618 REFRELE(session_p
, ses_lock_held
);
620 /* release the slot lock */
622 (void) pthread_mutex_unlock(&pslot
->sl_mutex
);
628 C_FindObjectsFinal(CK_SESSION_HANDLE sh
)
630 kms_session_t
*session_p
;
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
641 rv
= handle2session(sh
, &session_p
);
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
);