17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <pthread.h> 307c478bd9Sstevel@tonic-gate #include <stdlib.h> 317c478bd9Sstevel@tonic-gate #include <errno.h> 327c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 337c478bd9Sstevel@tonic-gate #include "kernelGlobal.h" 347c478bd9Sstevel@tonic-gate #include "kernelObject.h" 357c478bd9Sstevel@tonic-gate #include "kernelSession.h" 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <string.h> 387c478bd9Sstevel@tonic-gate #include <cryptoutil.h> 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate CK_RV 417c478bd9Sstevel@tonic-gate C_CreateObject(CK_SESSION_HANDLE hSession, 427c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pTemplate, 437c478bd9Sstevel@tonic-gate CK_ULONG ulCount, 447c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE_PTR phObject) 457c478bd9Sstevel@tonic-gate { 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate CK_RV rv; 487c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 497c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate if (!kernel_initialized) 527c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate if ((pTemplate == NULL) || (ulCount == 0) || 557c478bd9Sstevel@tonic-gate (phObject == NULL)) { 567c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 577c478bd9Sstevel@tonic-gate } 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session 617c478bd9Sstevel@tonic-gate * reference count. 627c478bd9Sstevel@tonic-gate */ 637c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 647c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 657c478bd9Sstevel@tonic-gate return (rv); 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate /* Create a new object. */ 687c478bd9Sstevel@tonic-gate rv = kernel_add_object(pTemplate, ulCount, phObject, session_p); 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* 717c478bd9Sstevel@tonic-gate * Decrement the session reference count. 727c478bd9Sstevel@tonic-gate * We do not hold the session lock. 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate return (rv); 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate CK_RV 817c478bd9Sstevel@tonic-gate C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, 827c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, 837c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE_PTR phNewObject) 847c478bd9Sstevel@tonic-gate { 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate CK_RV rv; 877c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 887c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 897c478bd9Sstevel@tonic-gate kernel_object_t *old_object; 907c478bd9Sstevel@tonic-gate kernel_object_t *new_object = NULL; 917c478bd9Sstevel@tonic-gate crypto_object_copy_t object_copy; 927c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj = FALSE; 937c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE; 947c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 957c478bd9Sstevel@tonic-gate int i, r; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate if (!kernel_initialized) 987c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* Check arguments */ 1017c478bd9Sstevel@tonic-gate if (((ulCount > 0) && (pTemplate == NULL)) || 1027c478bd9Sstevel@tonic-gate (phNewObject == NULL)) { 1037c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 1047c478bd9Sstevel@tonic-gate } 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate /* 1077c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session 1087c478bd9Sstevel@tonic-gate * reference count. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 1117c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 1127c478bd9Sstevel@tonic-gate return (rv); 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* Obtain the object pointer. */ 1157c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hObject, old_object, rv); 1167c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1177c478bd9Sstevel@tonic-gate /* 1187c478bd9Sstevel@tonic-gate * Decrement the session reference count. 1197c478bd9Sstevel@tonic-gate * We do not hold the session lock. 1207c478bd9Sstevel@tonic-gate */ 1217c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 1227c478bd9Sstevel@tonic-gate return (rv); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&old_object->object_mutex); 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate if (old_object->is_lib_obj) { 1287c478bd9Sstevel@tonic-gate /* 1297c478bd9Sstevel@tonic-gate * Copy the old object to a new object. 1307c478bd9Sstevel@tonic-gate * The 3rd argument with TRUE value indicates that 1317c478bd9Sstevel@tonic-gate * everything in the object will be duplicated. 1327c478bd9Sstevel@tonic-gate */ 1337c478bd9Sstevel@tonic-gate rv = kernel_copy_object(old_object, &new_object, B_TRUE, 1347c478bd9Sstevel@tonic-gate session_p); 1357c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&old_object->object_mutex); 136*01223cbaSmcpowers if ((rv != CKR_OK) || (new_object == NULL)) { 1377c478bd9Sstevel@tonic-gate /* 138*01223cbaSmcpowers * Most likely we ran out of space. 1397c478bd9Sstevel@tonic-gate * Decrement the session reference count. 1407c478bd9Sstevel@tonic-gate * We do not hold the session lock. 1417c478bd9Sstevel@tonic-gate */ 142*01223cbaSmcpowers OBJ_REFRELE(old_object); 1437c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 1447c478bd9Sstevel@tonic-gate return (rv); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate new_object->is_lib_obj = B_TRUE; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* Modify the object attribute if requested */ 1507c478bd9Sstevel@tonic-gate for (i = 0; i < ulCount; i++) { 1517c478bd9Sstevel@tonic-gate /* Set the requested attribute into the new object. */ 1527c478bd9Sstevel@tonic-gate rv = kernel_set_attribute(new_object, &pTemplate[i], 1537c478bd9Sstevel@tonic-gate B_TRUE, session_p); 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1567c478bd9Sstevel@tonic-gate kernel_cleanup_object(new_object); 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate /* 1597c478bd9Sstevel@tonic-gate * Decrement the session reference count. 1607c478bd9Sstevel@tonic-gate * We do not hold the session lock. 1617c478bd9Sstevel@tonic-gate */ 162*01223cbaSmcpowers OBJ_REFRELE(old_object); 1637c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 1647c478bd9Sstevel@tonic-gate return (rv); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* Insert the new object into this session's object list. */ 1697c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_object, session_p); 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * Decrement the session reference count. 1737c478bd9Sstevel@tonic-gate * We do not hold the session lock. 1747c478bd9Sstevel@tonic-gate */ 175*01223cbaSmcpowers OBJ_REFRELE(old_object); 1767c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /* set handle of the new object */ 1797c478bd9Sstevel@tonic-gate *phNewObject = (CK_ULONG)new_object; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate } else { 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * The old object was created in the HW provider. 1847c478bd9Sstevel@tonic-gate * First, create an object wrapper in library. 1857c478bd9Sstevel@tonic-gate */ 1867c478bd9Sstevel@tonic-gate new_object = calloc(1, sizeof (kernel_object_t)); 1877c478bd9Sstevel@tonic-gate if (new_object == NULL) { 188*01223cbaSmcpowers (void) pthread_mutex_unlock(&old_object->object_mutex); 189*01223cbaSmcpowers OBJ_REFRELE(old_object); 190*01223cbaSmcpowers REFRELE(session_p, ses_lock_held); 191*01223cbaSmcpowers return (CKR_HOST_MEMORY); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* Call CRYPTO_OBJECT_COPY ioctl to get a new object. */ 1957c478bd9Sstevel@tonic-gate object_copy.oc_session = session_p->k_session; 1967c478bd9Sstevel@tonic-gate object_copy.oc_handle = old_object->k_handle; 197*01223cbaSmcpowers (void) pthread_mutex_unlock(&old_object->object_mutex); 1987c478bd9Sstevel@tonic-gate object_copy.oc_count = ulCount; 1997c478bd9Sstevel@tonic-gate object_copy.oc_new_attributes = NULL; 2007c478bd9Sstevel@tonic-gate if (ulCount > 0) { 2017c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulCount, 2027c478bd9Sstevel@tonic-gate &object_copy.oc_new_attributes, &is_token_obj); 2037c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2047c478bd9Sstevel@tonic-gate goto failed_cleanup; 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_COPY, 2097c478bd9Sstevel@tonic-gate &object_copy)) < 0) { 2107c478bd9Sstevel@tonic-gate if (errno != EINTR) 2117c478bd9Sstevel@tonic-gate break; 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate if (r < 0) { 2147c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 2157c478bd9Sstevel@tonic-gate } else { 2167c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number( 2177c478bd9Sstevel@tonic-gate object_copy.oc_return_value); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* Free the attributes' space allocated for ioctl */ 2217c478bd9Sstevel@tonic-gate free_object_attributes(object_copy.oc_new_attributes, ulCount); 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2247c478bd9Sstevel@tonic-gate goto failed_cleanup; 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate /* 2287c478bd9Sstevel@tonic-gate * Store the kernel object handle in the object wrapper and 2297c478bd9Sstevel@tonic-gate * get the CKA_PRIVATE value of the new object. 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate new_object->k_handle = object_copy.oc_new_handle; 2327c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, new_object->k_handle, 2337c478bd9Sstevel@tonic-gate &is_pri_obj); 2347c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2357c478bd9Sstevel@tonic-gate goto failed_cleanup; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * Initialize other field of the object wrapper. 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate new_object->is_lib_obj = B_FALSE; 2427c478bd9Sstevel@tonic-gate new_object->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 2437c478bd9Sstevel@tonic-gate new_object->session_handle = (CK_SESSION_HANDLE)session_p; 2447c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_object->object_mutex, NULL); 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate if (is_pri_obj) 2477c478bd9Sstevel@tonic-gate new_object->bool_attr_mask |= PRIVATE_BOOL_ON; 2487c478bd9Sstevel@tonic-gate else 2497c478bd9Sstevel@tonic-gate new_object->bool_attr_mask &= ~PRIVATE_BOOL_ON; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate if (is_token_obj) 2527c478bd9Sstevel@tonic-gate new_object->bool_attr_mask |= TOKEN_BOOL_ON; 2537c478bd9Sstevel@tonic-gate else 2547c478bd9Sstevel@tonic-gate new_object->bool_attr_mask &= ~TOKEN_BOOL_ON; 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * Add the new copied object into the slot's token list 2587c478bd9Sstevel@tonic-gate * or the session list. We don't hold the slot lock. 2597c478bd9Sstevel@tonic-gate */ 2607c478bd9Sstevel@tonic-gate if (is_token_obj) { 2617c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * Decrement the session reference count. 2657c478bd9Sstevel@tonic-gate * We do not hold the session lock. 2667c478bd9Sstevel@tonic-gate */ 267*01223cbaSmcpowers OBJ_REFRELE(old_object); 2687c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* Add into the slot token object list. */ 2717c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_object, pslot); 2727c478bd9Sstevel@tonic-gate } else { 2737c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_object, session_p); 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate /* 2767c478bd9Sstevel@tonic-gate * Decrement the session reference count. 2777c478bd9Sstevel@tonic-gate * We do not hold the session lock. 2787c478bd9Sstevel@tonic-gate */ 279*01223cbaSmcpowers OBJ_REFRELE(old_object); 2807c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* set handle of the new object */ 2847c478bd9Sstevel@tonic-gate *phNewObject = (CK_ULONG)new_object; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate return (rv); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate failed_cleanup: 2907c478bd9Sstevel@tonic-gate if (new_object != NULL) { 2917c478bd9Sstevel@tonic-gate (void) free(new_object); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 294*01223cbaSmcpowers OBJ_REFRELE(old_object); 2957c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 2967c478bd9Sstevel@tonic-gate return (rv); 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate CK_RV 3017c478bd9Sstevel@tonic-gate C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) 3027c478bd9Sstevel@tonic-gate { 3037c478bd9Sstevel@tonic-gate CK_RV rv; 3047c478bd9Sstevel@tonic-gate kernel_object_t *object_p; 305*01223cbaSmcpowers kernel_session_t *session_p = (kernel_session_t *)(hSession); 3067c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 3077c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 3087c478bd9Sstevel@tonic-gate CK_SESSION_HANDLE creating_session; 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate if (!kernel_initialized) 3117c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 3127c478bd9Sstevel@tonic-gate 313*01223cbaSmcpowers /* 314*01223cbaSmcpowers * The reason that we don't call handle2session is because 315*01223cbaSmcpowers * the argument hSession may not be the creating_session of 316*01223cbaSmcpowers * the object to be destroyed, and we want to avoid the lock 317*01223cbaSmcpowers * contention. The handle2session will be called later for 318*01223cbaSmcpowers * the creating_session. 319*01223cbaSmcpowers */ 320*01223cbaSmcpowers if ((session_p == NULL) || 321*01223cbaSmcpowers (session_p->magic_marker != KERNELTOKEN_SESSION_MAGIC)) { 322*01223cbaSmcpowers return (CKR_SESSION_HANDLE_INVALID); 323*01223cbaSmcpowers } 3247c478bd9Sstevel@tonic-gate 325*01223cbaSmcpowers /* Obtain the object pointer without incrementing reference count. */ 326*01223cbaSmcpowers HANDLE2OBJECT_DESTROY(hObject, object_p, rv); 3277c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 328*01223cbaSmcpowers return (rv); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /* Only session objects can be destroyed at a read-only session. */ 3327c478bd9Sstevel@tonic-gate if ((session_p->ses_RO) && 3337c478bd9Sstevel@tonic-gate (object_p->bool_attr_mask & TOKEN_BOOL_ON)) { 334*01223cbaSmcpowers return (CKR_SESSION_READ_ONLY); 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate /* 3387c478bd9Sstevel@tonic-gate * If the object is a session object, obtain the session handle 3397c478bd9Sstevel@tonic-gate * which object belongs to. For a token object, we will use the 3407c478bd9Sstevel@tonic-gate * session handle from the caller, because the session used to 3417c478bd9Sstevel@tonic-gate * create the token object may no longer exist. 3427c478bd9Sstevel@tonic-gate */ 343*01223cbaSmcpowers if (!(object_p->bool_attr_mask & TOKEN_BOOL_ON)) 3447c478bd9Sstevel@tonic-gate creating_session = object_p->session_handle; 345*01223cbaSmcpowers else 346*01223cbaSmcpowers creating_session = hSession; 347*01223cbaSmcpowers 3487c478bd9Sstevel@tonic-gate rv = handle2session(creating_session, &session_p); 349*01223cbaSmcpowers if (rv != CKR_OK) { 3507c478bd9Sstevel@tonic-gate return (rv); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 353*01223cbaSmcpowers /* 354*01223cbaSmcpowers * Set OBJECT_IS_DELETING flag so any access to this 355*01223cbaSmcpowers * object will be rejected. 356*01223cbaSmcpowers */ 357*01223cbaSmcpowers (void) pthread_mutex_lock(&object_p->object_mutex); 358*01223cbaSmcpowers if (object_p->obj_delete_sync & OBJECT_IS_DELETING) { 359*01223cbaSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex); 360*01223cbaSmcpowers REFRELE(session_p, ses_lock_held); 361*01223cbaSmcpowers return (CKR_OBJECT_HANDLE_INVALID); 362*01223cbaSmcpowers } 363*01223cbaSmcpowers object_p->obj_delete_sync |= OBJECT_IS_DELETING; 364*01223cbaSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex); 365*01223cbaSmcpowers 3667c478bd9Sstevel@tonic-gate if (object_p->bool_attr_mask & TOKEN_BOOL_ON) { 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * The first FALSE boolean argument indicates that the caller 3697c478bd9Sstevel@tonic-gate * does not hold the slot lock. The second FALSE boolean 3707c478bd9Sstevel@tonic-gate * argument indicates that the caller wants to clean up the 3717c478bd9Sstevel@tonic-gate * object in the HW provider also. 3727c478bd9Sstevel@tonic-gate */ 3737c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 3747c478bd9Sstevel@tonic-gate rv = kernel_delete_token_object(pslot, session_p, object_p, 3757c478bd9Sstevel@tonic-gate B_FALSE, B_FALSE); 3767c478bd9Sstevel@tonic-gate } else { 3777c478bd9Sstevel@tonic-gate /* 3787c478bd9Sstevel@tonic-gate * The first FALSE boolean argument indicates that the caller 3797c478bd9Sstevel@tonic-gate * does not hold the session lock. The second FALSE boolean 3807c478bd9Sstevel@tonic-gate * argument indicates that the caller wants to clean the object 3817c478bd9Sstevel@tonic-gate * in the HW provider also. 3827c478bd9Sstevel@tonic-gate */ 3837c478bd9Sstevel@tonic-gate rv = kernel_delete_session_object(session_p, object_p, B_FALSE, 3847c478bd9Sstevel@tonic-gate B_FALSE); 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate /* 3877c478bd9Sstevel@tonic-gate * Decrement the session reference count. 3887c478bd9Sstevel@tonic-gate * We do not hold the session lock. 3897c478bd9Sstevel@tonic-gate */ 3907c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 3917c478bd9Sstevel@tonic-gate return (rv); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate CK_RV 3967c478bd9Sstevel@tonic-gate C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, 3977c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) 3987c478bd9Sstevel@tonic-gate { 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK, rv1 = CKR_OK; 4017c478bd9Sstevel@tonic-gate kernel_object_t *object_p; 4027c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 4037c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 4047c478bd9Sstevel@tonic-gate crypto_object_get_attribute_value_t obj_get_attr; 4057c478bd9Sstevel@tonic-gate int i, r; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate if (!kernel_initialized) 4087c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate if ((pTemplate == NULL) || (ulCount == 0)) 4117c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate /* 4147c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session 4157c478bd9Sstevel@tonic-gate * reference count. 4167c478bd9Sstevel@tonic-gate */ 4177c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 4187c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4197c478bd9Sstevel@tonic-gate return (rv); 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate /* Obtain the object pointer. */ 4227c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hObject, object_p, rv); 4237c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4247c478bd9Sstevel@tonic-gate /* 4257c478bd9Sstevel@tonic-gate * Decrement the session reference count. 4267c478bd9Sstevel@tonic-gate * We do not hold the session lock. 4277c478bd9Sstevel@tonic-gate */ 4287c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 4297c478bd9Sstevel@tonic-gate return (rv); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* Acquire the lock on the object. */ 4337c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&object_p->object_mutex); 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate if (object_p->is_lib_obj) { 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * The object was created in the library. The library 4387c478bd9Sstevel@tonic-gate * contains the value information of each attribute. 4397c478bd9Sstevel@tonic-gate */ 4407c478bd9Sstevel@tonic-gate for (i = 0; i < ulCount; i++) { 4417c478bd9Sstevel@tonic-gate /* 4427c478bd9Sstevel@tonic-gate * Get the value of each attribute in the template. 4437c478bd9Sstevel@tonic-gate * (We must process EVERY attribute in the template.) 4447c478bd9Sstevel@tonic-gate */ 4457c478bd9Sstevel@tonic-gate rv = kernel_get_attribute(object_p, &pTemplate[i]); 4467c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4477c478bd9Sstevel@tonic-gate /* At least we catch some type of error. */ 4487c478bd9Sstevel@tonic-gate rv1 = rv; 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate rv = rv1; 451*01223cbaSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex); 4527c478bd9Sstevel@tonic-gate } else { 4537c478bd9Sstevel@tonic-gate /* 4547c478bd9Sstevel@tonic-gate * The object was created in HW provider, call ioctl to get 4557c478bd9Sstevel@tonic-gate * the values of attributes. 4567c478bd9Sstevel@tonic-gate */ 4577c478bd9Sstevel@tonic-gate obj_get_attr.og_session = session_p->k_session; 4587c478bd9Sstevel@tonic-gate obj_get_attr.og_handle = object_p->k_handle; 459*01223cbaSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex); 4607c478bd9Sstevel@tonic-gate obj_get_attr.og_count = ulCount; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulCount, 4637c478bd9Sstevel@tonic-gate &obj_get_attr.og_attributes, NULL); 4647c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4657c478bd9Sstevel@tonic-gate goto clean_exit; 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE, 4697c478bd9Sstevel@tonic-gate &obj_get_attr)) < 0) { 4707c478bd9Sstevel@tonic-gate if (errno != EINTR) 4717c478bd9Sstevel@tonic-gate break; 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate if (r < 0) { 4747c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 4757c478bd9Sstevel@tonic-gate } else { 4767c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number( 4777c478bd9Sstevel@tonic-gate obj_get_attr.og_return_value); 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate /* 4817c478bd9Sstevel@tonic-gate * The error codes CKR_ATTRIBUTE_SENSITIVE, 4827c478bd9Sstevel@tonic-gate * CKR_ATTRIBUTE_TYPE_INVALID, and CKR_BUFFER_TOO_SMALL 4837c478bd9Sstevel@tonic-gate * do not denote true errors for this function. If a call 4847c478bd9Sstevel@tonic-gate * returns any of these three values, then the call must 4857c478bd9Sstevel@tonic-gate * nonetheless have processed every attribute in the 4867c478bd9Sstevel@tonic-gate * template. Every attribute in the template whose value 4877c478bd9Sstevel@tonic-gate * can be returned will be returned. 4887c478bd9Sstevel@tonic-gate */ 4897c478bd9Sstevel@tonic-gate if ((rv == CKR_OK) || 4907c478bd9Sstevel@tonic-gate (rv == CKR_ATTRIBUTE_SENSITIVE) || 4917c478bd9Sstevel@tonic-gate (rv == CKR_ATTRIBUTE_TYPE_INVALID) || 4927c478bd9Sstevel@tonic-gate (rv == CKR_BUFFER_TOO_SMALL)) { 4937c478bd9Sstevel@tonic-gate rv1 = get_object_attributes(pTemplate, ulCount, 4947c478bd9Sstevel@tonic-gate obj_get_attr.og_attributes); 4957c478bd9Sstevel@tonic-gate if (rv1 != CKR_OK) { 4967c478bd9Sstevel@tonic-gate rv = rv1; 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate /* Free the attributes' allocated for the ioctl call. */ 5017c478bd9Sstevel@tonic-gate free_object_attributes(obj_get_attr.og_attributes, ulCount); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate clean_exit: 5057c478bd9Sstevel@tonic-gate /* 5067c478bd9Sstevel@tonic-gate * Decrement the session reference count. 5077c478bd9Sstevel@tonic-gate * We do not hold the session lock. 5087c478bd9Sstevel@tonic-gate */ 509*01223cbaSmcpowers OBJ_REFRELE(object_p); 5107c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 5117c478bd9Sstevel@tonic-gate return (rv); 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate CK_RV 5167c478bd9Sstevel@tonic-gate C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, 5177c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) 5187c478bd9Sstevel@tonic-gate { 5197c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 5207c478bd9Sstevel@tonic-gate kernel_object_t *object_p; 5217c478bd9Sstevel@tonic-gate kernel_object_t *new_object = NULL; 5227c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 5237c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 5247c478bd9Sstevel@tonic-gate crypto_object_set_attribute_value_t obj_set_attr; 5257c478bd9Sstevel@tonic-gate int i, r; 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate if (!kernel_initialized) 5287c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate if ((pTemplate == NULL) || (ulCount == 0)) 5317c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate /* 5347c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session 5357c478bd9Sstevel@tonic-gate * reference count. 5367c478bd9Sstevel@tonic-gate */ 5377c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 5387c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 5397c478bd9Sstevel@tonic-gate return (rv); 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate /* Obtain the object pointer. */ 5427c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hObject, object_p, rv); 5437c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 5447c478bd9Sstevel@tonic-gate /* 5457c478bd9Sstevel@tonic-gate * Decrement the session reference count. 5467c478bd9Sstevel@tonic-gate * We do not hold the session lock. 5477c478bd9Sstevel@tonic-gate */ 5487c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 5497c478bd9Sstevel@tonic-gate return (rv); 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate /* lock the object */ 5537c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&object_p->object_mutex); 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate /* 5567c478bd9Sstevel@tonic-gate * If the object was created in the HW provider, changing its 5577c478bd9Sstevel@tonic-gate * attributes' values need to be done in the provider too. 5587c478bd9Sstevel@tonic-gate */ 5597c478bd9Sstevel@tonic-gate if (!object_p->is_lib_obj) { 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate /* Cannot modify a token object with a READ-ONLY session */ 5627c478bd9Sstevel@tonic-gate if (session_p->ses_RO && 5637c478bd9Sstevel@tonic-gate (object_p->bool_attr_mask & TOKEN_BOOL_ON)) { 5647c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex); 565*01223cbaSmcpowers rv = CKR_SESSION_READ_ONLY; 566*01223cbaSmcpowers goto clean_exit; 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate obj_set_attr.sa_session = session_p->k_session; 5707c478bd9Sstevel@tonic-gate obj_set_attr.sa_handle = object_p->k_handle; 571*01223cbaSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex); 5727c478bd9Sstevel@tonic-gate obj_set_attr.sa_count = ulCount; 5737c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulCount, 5747c478bd9Sstevel@tonic-gate &obj_set_attr.sa_attributes, NULL); 5757c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 576*01223cbaSmcpowers goto clean_exit; 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE, 5807c478bd9Sstevel@tonic-gate &obj_set_attr)) < 0) { 5817c478bd9Sstevel@tonic-gate if (errno != EINTR) 5827c478bd9Sstevel@tonic-gate break; 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate if (r < 0) { 5857c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 5867c478bd9Sstevel@tonic-gate } else { 5877c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number( 5887c478bd9Sstevel@tonic-gate obj_set_attr.sa_return_value); 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate /* Free the attributes' space allocated for the ioctl call. */ 5927c478bd9Sstevel@tonic-gate free_object_attributes(obj_set_attr.sa_attributes, ulCount); 593*01223cbaSmcpowers goto clean_exit; 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate /* 5977c478bd9Sstevel@tonic-gate * if we come here, the object must have been created in the 5987c478bd9Sstevel@tonic-gate * library. The work will be done completely in the library. 5997c478bd9Sstevel@tonic-gate * 6007c478bd9Sstevel@tonic-gate * Copy the old object to a new object. We work on the copied 6017c478bd9Sstevel@tonic-gate * version because in case of error we still keep the old one 6027c478bd9Sstevel@tonic-gate * intact. 6037c478bd9Sstevel@tonic-gate */ 6047c478bd9Sstevel@tonic-gate rv = kernel_copy_object(object_p, &new_object, B_FALSE, NULL); 6057c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex); 606*01223cbaSmcpowers if ((rv != CKR_OK) || (new_object == NULL)) { 6077c478bd9Sstevel@tonic-gate /* 608*01223cbaSmcpowers * Most likely we ran out of space. 6097c478bd9Sstevel@tonic-gate * Decrement the session reference count. 6107c478bd9Sstevel@tonic-gate * We do not hold the session lock. 6117c478bd9Sstevel@tonic-gate */ 612*01223cbaSmcpowers goto clean_exit; 6137c478bd9Sstevel@tonic-gate } 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate for (i = 0; i < ulCount; i++) { 6167c478bd9Sstevel@tonic-gate /* Set the requested attribute into the new object. */ 6177c478bd9Sstevel@tonic-gate rv = kernel_set_attribute(new_object, &pTemplate[i], B_FALSE, 6187c478bd9Sstevel@tonic-gate session_p); 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 6217c478bd9Sstevel@tonic-gate kernel_cleanup_object(new_object); 622*01223cbaSmcpowers goto clean_exit; 6237c478bd9Sstevel@tonic-gate } 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate /* 6277c478bd9Sstevel@tonic-gate * We've successfully set all the requested attributes. 6287c478bd9Sstevel@tonic-gate * Merge the new object with the old object, then destory 6297c478bd9Sstevel@tonic-gate * the new one. The reason to do the merging is because we 6307c478bd9Sstevel@tonic-gate * have to keep the original object handle (address of object). 6317c478bd9Sstevel@tonic-gate */ 6327c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&object_p->object_mutex); 6337c478bd9Sstevel@tonic-gate kernel_merge_object(object_p, new_object); 6347c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex); 635*01223cbaSmcpowers 636*01223cbaSmcpowers clean_exit: 637*01223cbaSmcpowers if (new_object != NULL) 638*01223cbaSmcpowers (void) free(new_object); 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate /* 6417c478bd9Sstevel@tonic-gate * Decrement the session reference count. 6427c478bd9Sstevel@tonic-gate * We do not hold the session lock. 6437c478bd9Sstevel@tonic-gate */ 644*01223cbaSmcpowers OBJ_REFRELE(object_p); 6457c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate return (rv); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate CK_RV 6527c478bd9Sstevel@tonic-gate C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, 6537c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulSize) 6547c478bd9Sstevel@tonic-gate { 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 6577c478bd9Sstevel@tonic-gate kernel_object_t *object_p; 6587c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 6597c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 6607c478bd9Sstevel@tonic-gate crypto_object_get_size_t obj_gs; 6617c478bd9Sstevel@tonic-gate int r; 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if (!kernel_initialized) 6647c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate /* Check if pulSize is valid */ 6677c478bd9Sstevel@tonic-gate if (pulSize == NULL) { 6687c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate /* 6727c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session 6737c478bd9Sstevel@tonic-gate * reference count. 6747c478bd9Sstevel@tonic-gate */ 6757c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 6767c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 6777c478bd9Sstevel@tonic-gate return (rv); 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate /* Obtain the object pointer. */ 6807c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hObject, object_p, rv); 6817c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 6827c478bd9Sstevel@tonic-gate /* 6837c478bd9Sstevel@tonic-gate * Decrement the session reference count. 6847c478bd9Sstevel@tonic-gate * We do not hold the session lock. 6857c478bd9Sstevel@tonic-gate */ 6867c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 6877c478bd9Sstevel@tonic-gate return (rv); 6887c478bd9Sstevel@tonic-gate } 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate /* Acquire the lock on the object. */ 6917c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&object_p->object_mutex); 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate if (!object_p->is_lib_obj) { 6947c478bd9Sstevel@tonic-gate /* 6957c478bd9Sstevel@tonic-gate * The object was created in HW provider, call the 6967c478bd9Sstevel@tonic-gate * CRYPTO_OBJECT_GET_SIZE ioctl. 6977c478bd9Sstevel@tonic-gate */ 6987c478bd9Sstevel@tonic-gate obj_gs.gs_session = session_p->k_session; 6997c478bd9Sstevel@tonic-gate obj_gs.gs_handle = object_p->k_handle; 700*01223cbaSmcpowers (void) pthread_mutex_unlock(&object_p->object_mutex); 7017c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_SIZE, 7027c478bd9Sstevel@tonic-gate &obj_gs)) < 0) { 7037c478bd9Sstevel@tonic-gate if (errno != EINTR) 7047c478bd9Sstevel@tonic-gate break; 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate if (r < 0) { 7077c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 7087c478bd9Sstevel@tonic-gate } else { 7097c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number( 7107c478bd9Sstevel@tonic-gate obj_gs.gs_return_value); 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 7147c478bd9Sstevel@tonic-gate *pulSize = obj_gs.gs_size; 7157c478bd9Sstevel@tonic-gate } 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate } else { 7187c478bd9Sstevel@tonic-gate rv = kernel_get_object_size(object_p, pulSize); 7197c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object_p->object_mutex); 720*01223cbaSmcpowers } 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate /* 7237c478bd9Sstevel@tonic-gate * Decrement the session reference count. 7247c478bd9Sstevel@tonic-gate * We do not hold the session lock. 7257c478bd9Sstevel@tonic-gate */ 726*01223cbaSmcpowers OBJ_REFRELE(object_p); 7277c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 7287c478bd9Sstevel@tonic-gate return (rv); 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate CK_RV 7337c478bd9Sstevel@tonic-gate C_FindObjectsInit(CK_SESSION_HANDLE sh, CK_ATTRIBUTE_PTR pTemplate, 7347c478bd9Sstevel@tonic-gate CK_ULONG ulCount) 7357c478bd9Sstevel@tonic-gate { 7367c478bd9Sstevel@tonic-gate CK_RV rv; 7377c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 7387c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 7397c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 7407c478bd9Sstevel@tonic-gate crypto_object_find_init_t obj_fi; 7417c478bd9Sstevel@tonic-gate int r; 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate if (!kernel_initialized) 7447c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate /* Check the arguments */ 7477c478bd9Sstevel@tonic-gate if ((ulCount > 0) && (pTemplate == NULL)) { 7487c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate /* 7527c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session 7537c478bd9Sstevel@tonic-gate * reference count. 7547c478bd9Sstevel@tonic-gate */ 7557c478bd9Sstevel@tonic-gate rv = handle2session(sh, &session_p); 7567c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 7577c478bd9Sstevel@tonic-gate return (rv); 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate /* Acquire the session lock */ 7607c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 7617c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate /* Check to see if find operation is already active */ 7647c478bd9Sstevel@tonic-gate if (session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE) { 7657c478bd9Sstevel@tonic-gate /* decrement the session count, and unlock the mutex */ 7667c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 7677c478bd9Sstevel@tonic-gate return (CKR_OPERATION_ACTIVE); 7687c478bd9Sstevel@tonic-gate } else { 7697c478bd9Sstevel@tonic-gate /* 7707c478bd9Sstevel@tonic-gate * This active flag will remain ON until application calls 7717c478bd9Sstevel@tonic-gate * C_FindObjectsFinal. 7727c478bd9Sstevel@tonic-gate */ 7737c478bd9Sstevel@tonic-gate session_p->find_objects.flags = CRYPTO_OPERATION_ACTIVE; 7747c478bd9Sstevel@tonic-gate } 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* 7787c478bd9Sstevel@tonic-gate * If the HW provider supports object creation, we call the 7797c478bd9Sstevel@tonic-gate * CRYPTO_OBJECT_FIND_INIT ioctl to initialize object finding. 7807c478bd9Sstevel@tonic-gate * Otherwise, all the objects are created in the library and we 7817c478bd9Sstevel@tonic-gate * do the find objects solely in the library. 7827c478bd9Sstevel@tonic-gate */ 7837c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 7847c478bd9Sstevel@tonic-gate if (pslot->sl_func_list.fl_object_create) { 7857c478bd9Sstevel@tonic-gate obj_fi.fi_session = session_p->k_session; 7867c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 7877c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 7887c478bd9Sstevel@tonic-gate obj_fi.fi_count = ulCount; 7897c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulCount, 7907c478bd9Sstevel@tonic-gate &obj_fi.fi_attributes, NULL); 7917c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 7927c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_INIT, 7937c478bd9Sstevel@tonic-gate &obj_fi)) < 0) { 7947c478bd9Sstevel@tonic-gate if (errno != EINTR) 7957c478bd9Sstevel@tonic-gate break; 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate if (r < 0) { 7987c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 7997c478bd9Sstevel@tonic-gate } else { 8007c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number( 8017c478bd9Sstevel@tonic-gate obj_fi.fi_return_value); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate /* Free the attributes' space allocated for the ioctl call. */ 8067c478bd9Sstevel@tonic-gate free_object_attributes(obj_fi.fi_attributes, ulCount); 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate } else { 8097c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 8107c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 8117c478bd9Sstevel@tonic-gate rv = kernel_find_objects_init(session_p, pTemplate, ulCount); 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 8157c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 8167c478bd9Sstevel@tonic-gate session_p->find_objects.flags = 0; 8177c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate /* decrement the session count, and unlock the mutex */ 8217c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 8227c478bd9Sstevel@tonic-gate return (rv); 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate CK_RV 8277c478bd9Sstevel@tonic-gate C_FindObjects(CK_SESSION_HANDLE sh, CK_OBJECT_HANDLE_PTR phObject, 8287c478bd9Sstevel@tonic-gate CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) 8297c478bd9Sstevel@tonic-gate { 8307c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 8317c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 8327c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 8337c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 8347c478bd9Sstevel@tonic-gate crypto_object_find_update_t obj_fu; 8357c478bd9Sstevel@tonic-gate int r; 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate if (!kernel_initialized) 8387c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate /* check for invalid arguments */ 8417c478bd9Sstevel@tonic-gate if (((phObject == NULL) && (ulMaxObjectCount != 0)) || 8427c478bd9Sstevel@tonic-gate (pulObjectCount == NULL)) { 8437c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 8447c478bd9Sstevel@tonic-gate } 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate if (ulMaxObjectCount == 0) { 8477c478bd9Sstevel@tonic-gate /* don't need to do anything, just return */ 8487c478bd9Sstevel@tonic-gate *pulObjectCount = 0; 8497c478bd9Sstevel@tonic-gate return (CKR_OK); 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate /* 8537c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session 8547c478bd9Sstevel@tonic-gate * reference count. 8557c478bd9Sstevel@tonic-gate */ 8567c478bd9Sstevel@tonic-gate rv = handle2session(sh, &session_p); 8577c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 8587c478bd9Sstevel@tonic-gate return (rv); 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate /* Acquire the slot lock */ 8617c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 8627c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&pslot->sl_mutex); 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate /* Acquire the session lock */ 8657c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 8667c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate /* Check to see if find operation is active */ 8697c478bd9Sstevel@tonic-gate if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) { 8707c478bd9Sstevel@tonic-gate rv = CKR_OPERATION_NOT_INITIALIZED; 8717c478bd9Sstevel@tonic-gate goto clean_exit; 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate /* 8757c478bd9Sstevel@tonic-gate * Similar to C_FindObjectInit(), if the HW provider supports object 8767c478bd9Sstevel@tonic-gate * creation, we call the respective ioctl to find objects. 8777c478bd9Sstevel@tonic-gate * Otherwise, all the objects are created in the library and we do 8787c478bd9Sstevel@tonic-gate * the find objects solely in the library. 8797c478bd9Sstevel@tonic-gate */ 8807c478bd9Sstevel@tonic-gate if (pslot->sl_func_list.fl_object_create) { 8817c478bd9Sstevel@tonic-gate obj_fu.fu_session = session_p->k_session; 8827c478bd9Sstevel@tonic-gate obj_fu.fu_max_count = ulMaxObjectCount; 8837c478bd9Sstevel@tonic-gate obj_fu.fu_handles = (char *)calloc(1, 8847c478bd9Sstevel@tonic-gate ulMaxObjectCount * sizeof (crypto_object_id_t)); 8857c478bd9Sstevel@tonic-gate if (obj_fu.fu_handles == NULL) { 8867c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 8877c478bd9Sstevel@tonic-gate goto clean_exit; 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_UPDATE, 8917c478bd9Sstevel@tonic-gate &obj_fu)) < 0) { 8927c478bd9Sstevel@tonic-gate if (errno != EINTR) 8937c478bd9Sstevel@tonic-gate break; 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate if (r < 0) { 8967c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 8977c478bd9Sstevel@tonic-gate } else { 8987c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number( 8997c478bd9Sstevel@tonic-gate obj_fu.fu_return_value); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 9037c478bd9Sstevel@tonic-gate rv = process_found_objects(session_p, phObject, 9047c478bd9Sstevel@tonic-gate pulObjectCount, obj_fu); 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate free(obj_fu.fu_handles); 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate } else { 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate kernel_find_objects(session_p, phObject, ulMaxObjectCount, 9117c478bd9Sstevel@tonic-gate pulObjectCount); 9127c478bd9Sstevel@tonic-gate rv = CKR_OK; 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate clean_exit: 9167c478bd9Sstevel@tonic-gate /* decrement the session count, and release the session lock */ 9177c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate /* release the slot lock */ 9207c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&pslot->sl_mutex); 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate return (rv); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate CK_RV 9277c478bd9Sstevel@tonic-gate C_FindObjectsFinal(CK_SESSION_HANDLE sh) 9287c478bd9Sstevel@tonic-gate { 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 9317c478bd9Sstevel@tonic-gate CK_RV rv; 9327c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 9337c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 9347c478bd9Sstevel@tonic-gate crypto_object_find_final_t obj_ff; 9357c478bd9Sstevel@tonic-gate int r; 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate if (!kernel_initialized) 9387c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate /* 9417c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session 9427c478bd9Sstevel@tonic-gate * reference count. 9437c478bd9Sstevel@tonic-gate */ 9447c478bd9Sstevel@tonic-gate rv = handle2session(sh, &session_p); 9457c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 9467c478bd9Sstevel@tonic-gate return (rv); 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate /* Acquire the session lock */ 9497c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 9507c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate /* Check to see if find operation is active */ 9537c478bd9Sstevel@tonic-gate if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) { 9547c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 9557c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED); 9567c478bd9Sstevel@tonic-gate } 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate /* 9597c478bd9Sstevel@tonic-gate * Similar to C_FindObjectInit(), if the HW provider supports object 9607c478bd9Sstevel@tonic-gate * creation, we need to call the CRYPTO_OBJECT_FIND_FINAL ioctl. 9617c478bd9Sstevel@tonic-gate */ 9627c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 9637c478bd9Sstevel@tonic-gate if (pslot->sl_func_list.fl_object_create) { 9647c478bd9Sstevel@tonic-gate obj_ff.ff_session = session_p->k_session; 9657c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_FINAL, 9667c478bd9Sstevel@tonic-gate &obj_ff)) < 0) { 9677c478bd9Sstevel@tonic-gate if (errno != EINTR) 9687c478bd9Sstevel@tonic-gate break; 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate if (r < 0) { 9717c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 9727c478bd9Sstevel@tonic-gate } else { 9737c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number( 9747c478bd9Sstevel@tonic-gate obj_ff.ff_return_value); 9757c478bd9Sstevel@tonic-gate } 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate /* only need to reset find_objects.flags */ 9787c478bd9Sstevel@tonic-gate if (rv == CKR_OK) { 9797c478bd9Sstevel@tonic-gate session_p->find_objects.flags = 0; 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate } else { 9837c478bd9Sstevel@tonic-gate /* 9847c478bd9Sstevel@tonic-gate * The find object operations were done in the library, we 9857c478bd9Sstevel@tonic-gate * need to cleanup find_objects context. 9867c478bd9Sstevel@tonic-gate */ 9877c478bd9Sstevel@tonic-gate kernel_find_objects_final(session_p); 9887c478bd9Sstevel@tonic-gate rv = CKR_OK; 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate /* decrement the session count, and release the lock */ 9927c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 9937c478bd9Sstevel@tonic-gate return (rv); 9947c478bd9Sstevel@tonic-gate } 995