1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <strings.h>
30*7c478bd9Sstevel@tonic-gate #include <errno.h>
31*7c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h>
33*7c478bd9Sstevel@tonic-gate #include "kernelGlobal.h"
34*7c478bd9Sstevel@tonic-gate #include "kernelSession.h"
35*7c478bd9Sstevel@tonic-gate #include "kernelObject.h"
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate static boolean_t
38*7c478bd9Sstevel@tonic-gate is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount)
39*7c478bd9Sstevel@tonic-gate {
40*7c478bd9Sstevel@tonic-gate 	int i;
41*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < ulAttributeCount; i++) {
42*7c478bd9Sstevel@tonic-gate 		if (pTemplate[i].type == CKA_CLASS &&
43*7c478bd9Sstevel@tonic-gate 		    *(CK_OBJECT_CLASS *)(pTemplate[i].pValue) ==
44*7c478bd9Sstevel@tonic-gate 		    CKO_SECRET_KEY)
45*7c478bd9Sstevel@tonic-gate 			return (B_TRUE);
46*7c478bd9Sstevel@tonic-gate 	}
47*7c478bd9Sstevel@tonic-gate 	return (B_FALSE);
48*7c478bd9Sstevel@tonic-gate }
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate CK_RV
52*7c478bd9Sstevel@tonic-gate C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
53*7c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
54*7c478bd9Sstevel@tonic-gate {
55*7c478bd9Sstevel@tonic-gate 	CK_RV			rv = CKR_OK;
56*7c478bd9Sstevel@tonic-gate 	kernel_session_t	*session_p;
57*7c478bd9Sstevel@tonic-gate 	kernel_object_t		*new_objp = NULL;
58*7c478bd9Sstevel@tonic-gate 	kernel_slot_t		*pslot;
59*7c478bd9Sstevel@tonic-gate 	boolean_t		ses_lock_held = B_FALSE;
60*7c478bd9Sstevel@tonic-gate 	CK_BBOOL		is_pri_obj;
61*7c478bd9Sstevel@tonic-gate 	CK_BBOOL		is_token_obj = FALSE;
62*7c478bd9Sstevel@tonic-gate 	crypto_mech_type_t	k_mech_type;
63*7c478bd9Sstevel@tonic-gate 	crypto_object_generate_key_t 	obj_gk;
64*7c478bd9Sstevel@tonic-gate 	int r;
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
67*7c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate 	/* Obtain the session pointer */
70*7c478bd9Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
71*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
72*7c478bd9Sstevel@tonic-gate 		return (rv);
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate 	if ((pMechanism == NULL) || (phKey == NULL)) {
75*7c478bd9Sstevel@tonic-gate 		rv = CKR_ARGUMENTS_BAD;
76*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
77*7c478bd9Sstevel@tonic-gate 	}
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate 	if ((pTemplate == NULL) && (ulCount != 0)) {
80*7c478bd9Sstevel@tonic-gate 		rv = CKR_ARGUMENTS_BAD;
81*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
82*7c478bd9Sstevel@tonic-gate 	}
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate 	/* Get the kernel's internal mechanism number. */
85*7c478bd9Sstevel@tonic-gate 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
86*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
87*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
88*7c478bd9Sstevel@tonic-gate 	}
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	/* Create an object wrapper in the library first */
91*7c478bd9Sstevel@tonic-gate 	new_objp = calloc(1, sizeof (kernel_object_t));
92*7c478bd9Sstevel@tonic-gate 	if (new_objp == NULL) {
93*7c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
94*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
95*7c478bd9Sstevel@tonic-gate 	}
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 	/* Process the attributes */
98*7c478bd9Sstevel@tonic-gate 	rv = process_object_attributes(pTemplate, ulCount,
99*7c478bd9Sstevel@tonic-gate 	    &obj_gk.gk_attributes, &is_token_obj);
100*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
101*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
102*7c478bd9Sstevel@tonic-gate 	}
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	/* Cannot create a token object with a READ-ONLY session. */
105*7c478bd9Sstevel@tonic-gate 	if (is_token_obj && session_p->ses_RO) {
106*7c478bd9Sstevel@tonic-gate 		free_object_attributes(obj_gk.gk_attributes, ulCount);
107*7c478bd9Sstevel@tonic-gate 		rv = CKR_SESSION_READ_ONLY;
108*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
109*7c478bd9Sstevel@tonic-gate 	}
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 	/* Call the CRYPTO_GENERATE_KEY ioctl */
112*7c478bd9Sstevel@tonic-gate 	obj_gk.gk_session = session_p->k_session;
113*7c478bd9Sstevel@tonic-gate 	obj_gk.gk_count = ulCount;
114*7c478bd9Sstevel@tonic-gate 	obj_gk.gk_mechanism.cm_type = k_mech_type;
115*7c478bd9Sstevel@tonic-gate 	obj_gk.gk_mechanism.cm_param = pMechanism->pParameter;
116*7c478bd9Sstevel@tonic-gate 	obj_gk.gk_mechanism.cm_param_len = pMechanism->ulParameterLen;
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY, &obj_gk)) < 0) {
119*7c478bd9Sstevel@tonic-gate 		if (errno != EINTR)
120*7c478bd9Sstevel@tonic-gate 			break;
121*7c478bd9Sstevel@tonic-gate 	}
122*7c478bd9Sstevel@tonic-gate 	if (r < 0) {
123*7c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
124*7c478bd9Sstevel@tonic-gate 	} else {
125*7c478bd9Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(obj_gk.gk_return_value);
126*7c478bd9Sstevel@tonic-gate 	}
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	free_object_attributes(obj_gk.gk_attributes, ulCount);
129*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
130*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
131*7c478bd9Sstevel@tonic-gate 	}
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	/* Get the value of the CKA_PRIVATE attribute. */
134*7c478bd9Sstevel@tonic-gate 	rv = get_cka_private_value(session_p, obj_gk.gk_handle, &is_pri_obj);
135*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
136*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
137*7c478bd9Sstevel@tonic-gate 	}
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate 	/*
140*7c478bd9Sstevel@tonic-gate 	 * Store the kernel object handle in the object wrapper and
141*7c478bd9Sstevel@tonic-gate 	 * initialize the library object.
142*7c478bd9Sstevel@tonic-gate 	 */
143*7c478bd9Sstevel@tonic-gate 	new_objp->k_handle = obj_gk.gk_handle;
144*7c478bd9Sstevel@tonic-gate 	new_objp->is_lib_obj = B_FALSE;
145*7c478bd9Sstevel@tonic-gate 	new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
146*7c478bd9Sstevel@tonic-gate 	new_objp->extra_attrlistp = NULL;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	if (is_pri_obj)
149*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
150*7c478bd9Sstevel@tonic-gate 	else
151*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	if (is_token_obj)
154*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
155*7c478bd9Sstevel@tonic-gate 	else
156*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_objp->object_mutex, NULL);
159*7c478bd9Sstevel@tonic-gate 	new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	/*
162*7c478bd9Sstevel@tonic-gate 	 * Add the new object to the slot's token object list if it is a
163*7c478bd9Sstevel@tonic-gate 	 * a token object. Otherwise, add it to the session's object list.
164*7c478bd9Sstevel@tonic-gate 	 */
165*7c478bd9Sstevel@tonic-gate 	if (is_token_obj) {
166*7c478bd9Sstevel@tonic-gate 		pslot = slot_table[session_p->ses_slotid];
167*7c478bd9Sstevel@tonic-gate 		kernel_add_token_object_to_slot(new_objp, pslot);
168*7c478bd9Sstevel@tonic-gate 	} else {
169*7c478bd9Sstevel@tonic-gate 		kernel_add_object_to_session(new_objp, session_p);
170*7c478bd9Sstevel@tonic-gate 	}
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	*phKey = (CK_OBJECT_HANDLE)new_objp;
173*7c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
174*7c478bd9Sstevel@tonic-gate 	return (rv);
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate failed_exit:
177*7c478bd9Sstevel@tonic-gate 	if (new_objp != NULL) {
178*7c478bd9Sstevel@tonic-gate 		(void) free(new_objp);
179*7c478bd9Sstevel@tonic-gate 	}
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
182*7c478bd9Sstevel@tonic-gate 	return (rv);
183*7c478bd9Sstevel@tonic-gate }
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate CK_RV
187*7c478bd9Sstevel@tonic-gate C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
188*7c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
189*7c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
190*7c478bd9Sstevel@tonic-gate     CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
191*7c478bd9Sstevel@tonic-gate {
192*7c478bd9Sstevel@tonic-gate 	CK_RV			rv = CKR_OK;
193*7c478bd9Sstevel@tonic-gate 	kernel_session_t	*session_p;
194*7c478bd9Sstevel@tonic-gate 	kernel_object_t		*new_pub_objp = NULL;
195*7c478bd9Sstevel@tonic-gate 	kernel_object_t		*new_pri_objp = NULL;
196*7c478bd9Sstevel@tonic-gate 	kernel_slot_t		*pslot;
197*7c478bd9Sstevel@tonic-gate 	boolean_t		ses_lock_held = B_FALSE;
198*7c478bd9Sstevel@tonic-gate 	CK_BBOOL		is_pri_obj1;
199*7c478bd9Sstevel@tonic-gate 	CK_BBOOL		is_pri_obj2;
200*7c478bd9Sstevel@tonic-gate 	CK_BBOOL		is_token_obj1 = FALSE;
201*7c478bd9Sstevel@tonic-gate 	CK_BBOOL		is_token_obj2 = FALSE;
202*7c478bd9Sstevel@tonic-gate 	crypto_mech_type_t	k_mech_type;
203*7c478bd9Sstevel@tonic-gate 	crypto_object_generate_key_pair_t 	obj_kp;
204*7c478bd9Sstevel@tonic-gate 	int r;
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
207*7c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 	/* Obtain the session pointer. */
210*7c478bd9Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
211*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
212*7c478bd9Sstevel@tonic-gate 		return (rv);
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 	if ((pMechanism == NULL) || (phPublicKey == NULL) ||
215*7c478bd9Sstevel@tonic-gate 	    (phPrivateKey == NULL)) {
216*7c478bd9Sstevel@tonic-gate 		rv = CKR_ARGUMENTS_BAD;
217*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
218*7c478bd9Sstevel@tonic-gate 	}
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	if ((pPublicKeyTemplate == NULL) && (ulPublicKeyAttributeCount != 0)) {
221*7c478bd9Sstevel@tonic-gate 		rv = CKR_ARGUMENTS_BAD;
222*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
223*7c478bd9Sstevel@tonic-gate 	}
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	if ((pPrivateKeyTemplate == NULL) &&
226*7c478bd9Sstevel@tonic-gate 	    (ulPrivateKeyAttributeCount != 0)) {
227*7c478bd9Sstevel@tonic-gate 		rv = CKR_ARGUMENTS_BAD;
228*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
229*7c478bd9Sstevel@tonic-gate 	}
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	/* Get the kernel's internal mechanism number. */
232*7c478bd9Sstevel@tonic-gate 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
233*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
234*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
235*7c478bd9Sstevel@tonic-gate 	}
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	/* Create an object wrapper for the public key */
238*7c478bd9Sstevel@tonic-gate 	new_pub_objp = calloc(1, sizeof (kernel_object_t));
239*7c478bd9Sstevel@tonic-gate 	if (new_pub_objp == NULL) {
240*7c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
241*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
242*7c478bd9Sstevel@tonic-gate 	}
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 	/* Create an object wrapper for the private key. */
245*7c478bd9Sstevel@tonic-gate 	new_pri_objp = calloc(1, sizeof (kernel_object_t));
246*7c478bd9Sstevel@tonic-gate 	if (new_pri_objp == NULL) {
247*7c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
248*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
249*7c478bd9Sstevel@tonic-gate 	}
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	/* Process the public key attributes. */
252*7c478bd9Sstevel@tonic-gate 	rv = process_object_attributes(pPublicKeyTemplate,
253*7c478bd9Sstevel@tonic-gate 	    ulPublicKeyAttributeCount, &obj_kp.kp_public_attributes,
254*7c478bd9Sstevel@tonic-gate 	    &is_token_obj1);
255*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
256*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
257*7c478bd9Sstevel@tonic-gate 	}
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 	/* Cannot create a token object with a READ-ONLY session. */
260*7c478bd9Sstevel@tonic-gate 	if (is_token_obj1 && session_p->ses_RO) {
261*7c478bd9Sstevel@tonic-gate 		free_object_attributes(obj_kp.kp_public_attributes,
262*7c478bd9Sstevel@tonic-gate 		    ulPublicKeyAttributeCount);
263*7c478bd9Sstevel@tonic-gate 		rv = CKR_SESSION_READ_ONLY;
264*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
265*7c478bd9Sstevel@tonic-gate 	}
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate 	/* Process the private key attributes. */
268*7c478bd9Sstevel@tonic-gate 	rv = process_object_attributes(pPrivateKeyTemplate,
269*7c478bd9Sstevel@tonic-gate 	    ulPrivateKeyAttributeCount, &obj_kp.kp_private_attributes,
270*7c478bd9Sstevel@tonic-gate 	    &is_token_obj2);
271*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
272*7c478bd9Sstevel@tonic-gate 		free_object_attributes(obj_kp.kp_public_attributes,
273*7c478bd9Sstevel@tonic-gate 		    ulPublicKeyAttributeCount);
274*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
275*7c478bd9Sstevel@tonic-gate 	}
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	/*
278*7c478bd9Sstevel@tonic-gate 	 * The public key and the private key need to contain the same
279*7c478bd9Sstevel@tonic-gate 	 * attribute values for CKA_TOKEN.
280*7c478bd9Sstevel@tonic-gate 	 */
281*7c478bd9Sstevel@tonic-gate 	if (is_token_obj1 != is_token_obj2) {
282*7c478bd9Sstevel@tonic-gate 		free_object_attributes(obj_kp.kp_public_attributes,
283*7c478bd9Sstevel@tonic-gate 		    ulPublicKeyAttributeCount);
284*7c478bd9Sstevel@tonic-gate 		free_object_attributes(obj_kp.kp_private_attributes,
285*7c478bd9Sstevel@tonic-gate 		    ulPrivateKeyAttributeCount);
286*7c478bd9Sstevel@tonic-gate 		rv = CKR_ATTRIBUTE_VALUE_INVALID;
287*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
288*7c478bd9Sstevel@tonic-gate 	}
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate 	/* Call the CRYPTO_GENERATE_KEY_PAIR ioctl. */
291*7c478bd9Sstevel@tonic-gate 	obj_kp.kp_session = session_p-> k_session;
292*7c478bd9Sstevel@tonic-gate 	obj_kp.kp_mechanism.cm_type = k_mech_type;
293*7c478bd9Sstevel@tonic-gate 	obj_kp.kp_mechanism.cm_param = pMechanism->pParameter;
294*7c478bd9Sstevel@tonic-gate 	obj_kp.kp_mechanism.cm_param_len = pMechanism->ulParameterLen;
295*7c478bd9Sstevel@tonic-gate 	obj_kp.kp_public_count = ulPublicKeyAttributeCount;
296*7c478bd9Sstevel@tonic-gate 	obj_kp.kp_private_count = ulPrivateKeyAttributeCount;
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY_PAIR, &obj_kp)) < 0) {
299*7c478bd9Sstevel@tonic-gate 		if (errno != EINTR)
300*7c478bd9Sstevel@tonic-gate 			break;
301*7c478bd9Sstevel@tonic-gate 	}
302*7c478bd9Sstevel@tonic-gate 	if (r < 0) {
303*7c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
304*7c478bd9Sstevel@tonic-gate 	} else {
305*7c478bd9Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(obj_kp.kp_return_value);
306*7c478bd9Sstevel@tonic-gate 	}
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	free_object_attributes(obj_kp.kp_public_attributes,
309*7c478bd9Sstevel@tonic-gate 	    ulPublicKeyAttributeCount);
310*7c478bd9Sstevel@tonic-gate 	free_object_attributes(obj_kp.kp_private_attributes,
311*7c478bd9Sstevel@tonic-gate 	    ulPrivateKeyAttributeCount);
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
314*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
315*7c478bd9Sstevel@tonic-gate 	}
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 	/* Get the CKA_PRIVATE value for the key pair. */
318*7c478bd9Sstevel@tonic-gate 	rv = get_cka_private_value(session_p, obj_kp.kp_public_handle,
319*7c478bd9Sstevel@tonic-gate 	    &is_pri_obj1);
320*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
321*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
322*7c478bd9Sstevel@tonic-gate 	}
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 	rv = get_cka_private_value(session_p, obj_kp.kp_private_handle,
325*7c478bd9Sstevel@tonic-gate 	    &is_pri_obj2);
326*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
327*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
328*7c478bd9Sstevel@tonic-gate 	}
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	/*
331*7c478bd9Sstevel@tonic-gate 	 * Store the kernel public key handle into the public key object and
332*7c478bd9Sstevel@tonic-gate 	 * finish the public key object initialization.
333*7c478bd9Sstevel@tonic-gate 	 */
334*7c478bd9Sstevel@tonic-gate 	new_pub_objp->is_lib_obj = B_FALSE;
335*7c478bd9Sstevel@tonic-gate 	new_pub_objp->k_handle = obj_kp.kp_public_handle;
336*7c478bd9Sstevel@tonic-gate 	new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
337*7c478bd9Sstevel@tonic-gate 	new_pub_objp->extra_attrlistp = NULL;
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	if (is_pri_obj1)
340*7c478bd9Sstevel@tonic-gate 		new_pub_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
341*7c478bd9Sstevel@tonic-gate 	else
342*7c478bd9Sstevel@tonic-gate 		new_pub_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 	if (is_token_obj1)
345*7c478bd9Sstevel@tonic-gate 		new_pub_objp->bool_attr_mask |= TOKEN_BOOL_ON;
346*7c478bd9Sstevel@tonic-gate 	else
347*7c478bd9Sstevel@tonic-gate 		new_pub_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
350*7c478bd9Sstevel@tonic-gate 	new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	/*
353*7c478bd9Sstevel@tonic-gate 	 * Store the kernel private key handle into the private key object
354*7c478bd9Sstevel@tonic-gate 	 * and finish the private key object initialization.
355*7c478bd9Sstevel@tonic-gate 	 */
356*7c478bd9Sstevel@tonic-gate 	new_pri_objp->is_lib_obj = B_FALSE;
357*7c478bd9Sstevel@tonic-gate 	new_pri_objp->k_handle = obj_kp.kp_private_handle;
358*7c478bd9Sstevel@tonic-gate 	new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
359*7c478bd9Sstevel@tonic-gate 	new_pri_objp->extra_attrlistp = NULL;
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	if (is_pri_obj2)
362*7c478bd9Sstevel@tonic-gate 		new_pri_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
363*7c478bd9Sstevel@tonic-gate 	else
364*7c478bd9Sstevel@tonic-gate 		new_pri_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 	if (is_token_obj2)
367*7c478bd9Sstevel@tonic-gate 		new_pri_objp->bool_attr_mask |= TOKEN_BOOL_ON;
368*7c478bd9Sstevel@tonic-gate 	else
369*7c478bd9Sstevel@tonic-gate 		new_pri_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
372*7c478bd9Sstevel@tonic-gate 	new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 	/*
375*7c478bd9Sstevel@tonic-gate 	 * Add the new pub/pri objects to the slot's token list if they are
376*7c478bd9Sstevel@tonic-gate 	 * token objects. Otherwise, add them to the session's object list.
377*7c478bd9Sstevel@tonic-gate 	 */
378*7c478bd9Sstevel@tonic-gate 	if (is_token_obj1) { /* is_token_obj1 == is_token_obj2 */
379*7c478bd9Sstevel@tonic-gate 		pslot = slot_table[session_p->ses_slotid];
380*7c478bd9Sstevel@tonic-gate 		kernel_add_token_object_to_slot(new_pub_objp, pslot);
381*7c478bd9Sstevel@tonic-gate 		kernel_add_token_object_to_slot(new_pri_objp, pslot);
382*7c478bd9Sstevel@tonic-gate 	} else {
383*7c478bd9Sstevel@tonic-gate 		kernel_add_object_to_session(new_pub_objp, session_p);
384*7c478bd9Sstevel@tonic-gate 		kernel_add_object_to_session(new_pri_objp, session_p);
385*7c478bd9Sstevel@tonic-gate 	}
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 	*phPublicKey = (CK_OBJECT_HANDLE)new_pub_objp;
388*7c478bd9Sstevel@tonic-gate 	*phPrivateKey = (CK_OBJECT_HANDLE)new_pri_objp;
389*7c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
390*7c478bd9Sstevel@tonic-gate 	return (rv);
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate failed_exit:
393*7c478bd9Sstevel@tonic-gate 	if (new_pub_objp != NULL) {
394*7c478bd9Sstevel@tonic-gate 		(void) free(new_pub_objp);
395*7c478bd9Sstevel@tonic-gate 	}
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	if (new_pri_objp != NULL) {
398*7c478bd9Sstevel@tonic-gate 		(void) free(new_pri_objp);
399*7c478bd9Sstevel@tonic-gate 	}
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
402*7c478bd9Sstevel@tonic-gate 	return (rv);
403*7c478bd9Sstevel@tonic-gate }
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate CK_RV
407*7c478bd9Sstevel@tonic-gate C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
408*7c478bd9Sstevel@tonic-gate     CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
409*7c478bd9Sstevel@tonic-gate     CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
410*7c478bd9Sstevel@tonic-gate {
411*7c478bd9Sstevel@tonic-gate 	CK_RV			rv = CKR_OK;
412*7c478bd9Sstevel@tonic-gate 	kernel_session_t	*session_p;
413*7c478bd9Sstevel@tonic-gate 	boolean_t		ses_lock_held = B_FALSE;
414*7c478bd9Sstevel@tonic-gate 	kernel_object_t		*wrappingkey_p;
415*7c478bd9Sstevel@tonic-gate 	kernel_object_t		*key_p;
416*7c478bd9Sstevel@tonic-gate 	crypto_mech_type_t	k_mech_type;
417*7c478bd9Sstevel@tonic-gate 	crypto_object_wrap_key_t obj_wrapkey;
418*7c478bd9Sstevel@tonic-gate 	int r;
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
421*7c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 	if (pulWrappedKeyLen == NULL || pMechanism == NULL) {
424*7c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
425*7c478bd9Sstevel@tonic-gate 	}
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 	/*
428*7c478bd9Sstevel@tonic-gate 	 * Obtain the session pointer.  Also, increment the session
429*7c478bd9Sstevel@tonic-gate 	 * reference count.
430*7c478bd9Sstevel@tonic-gate 	 */
431*7c478bd9Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
432*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
433*7c478bd9Sstevel@tonic-gate 		return (rv);
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 	/* Get the kernel's internal mechanism number. */
436*7c478bd9Sstevel@tonic-gate 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
437*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
438*7c478bd9Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
439*7c478bd9Sstevel@tonic-gate 		return (rv);
440*7c478bd9Sstevel@tonic-gate 	}
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate 	/* Obtain the wrapping key object pointer. */
443*7c478bd9Sstevel@tonic-gate 	HANDLE2OBJECT(hWrappingKey, wrappingkey_p, rv);
444*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
445*7c478bd9Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
446*7c478bd9Sstevel@tonic-gate 		return (rv);
447*7c478bd9Sstevel@tonic-gate 	}
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 	/* Obtain the to_be_wrapped key object pointer. */
450*7c478bd9Sstevel@tonic-gate 	HANDLE2OBJECT(hKey, key_p, rv);
451*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
452*7c478bd9Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
453*7c478bd9Sstevel@tonic-gate 		return (rv);
454*7c478bd9Sstevel@tonic-gate 	}
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 	/* Make the CRYPTO_OBJECT_WRAP_KEY ioctl call. */
457*7c478bd9Sstevel@tonic-gate 	obj_wrapkey.wk_session = session_p->k_session;
458*7c478bd9Sstevel@tonic-gate 	obj_wrapkey.wk_mechanism.cm_type = k_mech_type;
459*7c478bd9Sstevel@tonic-gate 	obj_wrapkey.wk_mechanism.cm_param = pMechanism->pParameter;
460*7c478bd9Sstevel@tonic-gate 	obj_wrapkey.wk_mechanism.cm_param_len = pMechanism->ulParameterLen;
461*7c478bd9Sstevel@tonic-gate 	obj_wrapkey.wk_wrapping_key.ck_format = CRYPTO_KEY_REFERENCE;
462*7c478bd9Sstevel@tonic-gate 	obj_wrapkey.wk_wrapping_key.ck_obj_id = wrappingkey_p->k_handle;
463*7c478bd9Sstevel@tonic-gate 	obj_wrapkey.wk_object_handle = key_p->k_handle;
464*7c478bd9Sstevel@tonic-gate 	obj_wrapkey.wk_wrapped_key_len = *pulWrappedKeyLen;
465*7c478bd9Sstevel@tonic-gate 	obj_wrapkey.wk_wrapped_key = (char *)pWrappedKey;
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_WRAP_KEY, &obj_wrapkey)) < 0) {
468*7c478bd9Sstevel@tonic-gate 		if (errno != EINTR)
469*7c478bd9Sstevel@tonic-gate 			break;
470*7c478bd9Sstevel@tonic-gate 	}
471*7c478bd9Sstevel@tonic-gate 	if (r < 0) {
472*7c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
473*7c478bd9Sstevel@tonic-gate 	} else {
474*7c478bd9Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(obj_wrapkey.wk_return_value);
475*7c478bd9Sstevel@tonic-gate 	}
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate 	/*
478*7c478bd9Sstevel@tonic-gate 	 * Besides rv == CKR_OK, we will set the value of pulWrappedKeyLen
479*7c478bd9Sstevel@tonic-gate 	 * when the applciation-supplied wrapped key buffer is too small.
480*7c478bd9Sstevel@tonic-gate 	 * The situation that the application only asks for the length of
481*7c478bd9Sstevel@tonic-gate 	 * the wrapped key is covered in rv == CKR_OK.
482*7c478bd9Sstevel@tonic-gate 	 */
483*7c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) {
484*7c478bd9Sstevel@tonic-gate 		*pulWrappedKeyLen = obj_wrapkey.wk_wrapped_key_len;
485*7c478bd9Sstevel@tonic-gate 	}
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
488*7c478bd9Sstevel@tonic-gate 	return (rv);
489*7c478bd9Sstevel@tonic-gate }
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate CK_RV
493*7c478bd9Sstevel@tonic-gate C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
494*7c478bd9Sstevel@tonic-gate     CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey,
495*7c478bd9Sstevel@tonic-gate     CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
496*7c478bd9Sstevel@tonic-gate     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
497*7c478bd9Sstevel@tonic-gate {
498*7c478bd9Sstevel@tonic-gate 	CK_RV			rv = CKR_OK;
499*7c478bd9Sstevel@tonic-gate 	kernel_session_t	*session_p;
500*7c478bd9Sstevel@tonic-gate 	kernel_object_t		*unwrappingkey_p;
501*7c478bd9Sstevel@tonic-gate 	kernel_object_t		*new_objp = NULL;
502*7c478bd9Sstevel@tonic-gate 	kernel_slot_t		*pslot;
503*7c478bd9Sstevel@tonic-gate 	boolean_t		ses_lock_held = B_FALSE;
504*7c478bd9Sstevel@tonic-gate 	CK_BBOOL		is_pri_obj;
505*7c478bd9Sstevel@tonic-gate 	CK_BBOOL		is_token_obj = FALSE;
506*7c478bd9Sstevel@tonic-gate 	CK_MECHANISM_INFO	info;
507*7c478bd9Sstevel@tonic-gate 	uint32_t		k_mi_flags;
508*7c478bd9Sstevel@tonic-gate 	CK_BYTE			*clear_key_val = NULL;
509*7c478bd9Sstevel@tonic-gate 	CK_ULONG 		ulDataLen;
510*7c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE_PTR	newTemplate = NULL;
511*7c478bd9Sstevel@tonic-gate 	CK_ULONG		templ_size;
512*7c478bd9Sstevel@tonic-gate 	crypto_mech_type_t	k_mech_type;
513*7c478bd9Sstevel@tonic-gate 	crypto_object_unwrap_key_t obj_unwrapkey;
514*7c478bd9Sstevel@tonic-gate 	int r;
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
517*7c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 	if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL) {
520*7c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
521*7c478bd9Sstevel@tonic-gate 	}
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	if ((pTemplate == NULL) && (ulAttributeCount != 0)) {
524*7c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
525*7c478bd9Sstevel@tonic-gate 	}
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate 	/* Obtain the session pointer. */
528*7c478bd9Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
529*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
530*7c478bd9Sstevel@tonic-gate 		return (rv);
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 	/* Obtain the wrapping key object pointer. */
533*7c478bd9Sstevel@tonic-gate 	HANDLE2OBJECT(hUnwrappingKey, unwrappingkey_p, rv);
534*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
535*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
536*7c478bd9Sstevel@tonic-gate 	}
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate 	/*
539*7c478bd9Sstevel@tonic-gate 	 * If the HW provider doesn't support C_UnwrapKey, we will try
540*7c478bd9Sstevel@tonic-gate 	 * to emulate it in the library.
541*7c478bd9Sstevel@tonic-gate 	 */
542*7c478bd9Sstevel@tonic-gate 	pslot = slot_table[session_p->ses_slotid];
543*7c478bd9Sstevel@tonic-gate 	if ((pslot->sl_func_list.fl_object_create == B_FALSE) &&
544*7c478bd9Sstevel@tonic-gate 	    (pslot->sl_func_list.fl_key_unwrap == B_FALSE)) {
545*7c478bd9Sstevel@tonic-gate 		rv = get_mechanism_info(pslot, pMechanism->mechanism, &info,
546*7c478bd9Sstevel@tonic-gate 		    &k_mi_flags);
547*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
548*7c478bd9Sstevel@tonic-gate 			goto failed_exit;
549*7c478bd9Sstevel@tonic-gate 		}
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate 		/*
552*7c478bd9Sstevel@tonic-gate 		 * If the mechanism flag doesn't have CKF_UNWRAP, and it's
553*7c478bd9Sstevel@tonic-gate 		 * an unwrapping of a secret key object, then help this
554*7c478bd9Sstevel@tonic-gate 		 * out with a decryption followed by an object creation.
555*7c478bd9Sstevel@tonic-gate 		 */
556*7c478bd9Sstevel@tonic-gate 		if (!(k_mi_flags & CRYPTO_FG_UNWRAP) &&
557*7c478bd9Sstevel@tonic-gate 		    (k_mi_flags & CRYPTO_FG_DECRYPT) &&
558*7c478bd9Sstevel@tonic-gate 		    (is_secret_key_template(pTemplate, ulAttributeCount))) {
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 			/* First allocate space for the recovered key value */
561*7c478bd9Sstevel@tonic-gate 			clear_key_val = malloc(ulWrappedKeyLen);
562*7c478bd9Sstevel@tonic-gate 			if (clear_key_val == NULL) {
563*7c478bd9Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
564*7c478bd9Sstevel@tonic-gate 				goto failed_exit;
565*7c478bd9Sstevel@tonic-gate 			}
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 			rv = kernel_decrypt_init(session_p, unwrappingkey_p,
568*7c478bd9Sstevel@tonic-gate 			    pMechanism);
569*7c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
570*7c478bd9Sstevel@tonic-gate 				goto failed_exit;
571*7c478bd9Sstevel@tonic-gate 			}
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 			ulDataLen = ulWrappedKeyLen;
574*7c478bd9Sstevel@tonic-gate 			rv = kernel_decrypt(session_p, pWrappedKey,
575*7c478bd9Sstevel@tonic-gate 			    ulWrappedKeyLen, clear_key_val, &ulDataLen);
576*7c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
577*7c478bd9Sstevel@tonic-gate 				goto failed_exit;
578*7c478bd9Sstevel@tonic-gate 			}
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 			/* Now add the CKA_VALUE attribute to template */
581*7c478bd9Sstevel@tonic-gate 			templ_size = ulAttributeCount * sizeof (CK_ATTRIBUTE);
582*7c478bd9Sstevel@tonic-gate 			newTemplate = malloc(templ_size +
583*7c478bd9Sstevel@tonic-gate 			    sizeof (CK_ATTRIBUTE));
584*7c478bd9Sstevel@tonic-gate 			if (newTemplate == NULL) {
585*7c478bd9Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
586*7c478bd9Sstevel@tonic-gate 				goto failed_exit;
587*7c478bd9Sstevel@tonic-gate 			}
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate 			bcopy(pTemplate, newTemplate, templ_size);
590*7c478bd9Sstevel@tonic-gate 			newTemplate[ulAttributeCount].type = CKA_VALUE;
591*7c478bd9Sstevel@tonic-gate 			newTemplate[ulAttributeCount].pValue = clear_key_val;
592*7c478bd9Sstevel@tonic-gate 			newTemplate[ulAttributeCount].ulValueLen = ulDataLen;
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 			/* Finally create the key, based on the new template */
595*7c478bd9Sstevel@tonic-gate 			rv = kernel_add_object(newTemplate,
596*7c478bd9Sstevel@tonic-gate 			    ulAttributeCount + 1, phKey, session_p);
597*7c478bd9Sstevel@tonic-gate 			(void) free(clear_key_val);
598*7c478bd9Sstevel@tonic-gate 			(void) free(newTemplate);
599*7c478bd9Sstevel@tonic-gate 			REFRELE(session_p, ses_lock_held);
600*7c478bd9Sstevel@tonic-gate 			return (rv);
601*7c478bd9Sstevel@tonic-gate 		} else {
602*7c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
603*7c478bd9Sstevel@tonic-gate 			goto failed_exit;
604*7c478bd9Sstevel@tonic-gate 		}
605*7c478bd9Sstevel@tonic-gate 	}
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate 	/*
608*7c478bd9Sstevel@tonic-gate 	 * If we come here, the HW provider must have registered the unwrapkey
609*7c478bd9Sstevel@tonic-gate 	 * entry.  Therefore, the unwrap key will be performed in the HW
610*7c478bd9Sstevel@tonic-gate 	 * provider.
611*7c478bd9Sstevel@tonic-gate 	 */
612*7c478bd9Sstevel@tonic-gate 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
613*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
614*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
615*7c478bd9Sstevel@tonic-gate 	}
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 	/* Create an object wrapper for the new key in the library first */
618*7c478bd9Sstevel@tonic-gate 	new_objp = calloc(1, sizeof (kernel_object_t));
619*7c478bd9Sstevel@tonic-gate 	if (new_objp == NULL) {
620*7c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
621*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
622*7c478bd9Sstevel@tonic-gate 	}
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	/* Process the attributes */
625*7c478bd9Sstevel@tonic-gate 	rv = process_object_attributes(pTemplate, ulAttributeCount,
626*7c478bd9Sstevel@tonic-gate 	    &obj_unwrapkey.uk_attributes, &is_token_obj);
627*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
628*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
629*7c478bd9Sstevel@tonic-gate 	}
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate 	/* Cannot create a token object with a READ-ONLY session. */
632*7c478bd9Sstevel@tonic-gate 	if (is_token_obj && session_p->ses_RO) {
633*7c478bd9Sstevel@tonic-gate 		free_object_attributes(obj_unwrapkey.uk_attributes,
634*7c478bd9Sstevel@tonic-gate 		    ulAttributeCount);
635*7c478bd9Sstevel@tonic-gate 		rv = CKR_SESSION_READ_ONLY;
636*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
637*7c478bd9Sstevel@tonic-gate 	}
638*7c478bd9Sstevel@tonic-gate 
639*7c478bd9Sstevel@tonic-gate 	/* Make the CRYPTO_UNWRAP_KEY ioctl call. */
640*7c478bd9Sstevel@tonic-gate 	obj_unwrapkey.uk_session = session_p->k_session;
641*7c478bd9Sstevel@tonic-gate 	obj_unwrapkey.uk_mechanism.cm_type = k_mech_type;
642*7c478bd9Sstevel@tonic-gate 	obj_unwrapkey.uk_mechanism.cm_param = pMechanism->pParameter;
643*7c478bd9Sstevel@tonic-gate 	obj_unwrapkey.uk_mechanism.cm_param_len = pMechanism->ulParameterLen;
644*7c478bd9Sstevel@tonic-gate 	obj_unwrapkey.uk_unwrapping_key.ck_format = CRYPTO_KEY_REFERENCE;
645*7c478bd9Sstevel@tonic-gate 	obj_unwrapkey.uk_unwrapping_key.ck_obj_id = unwrappingkey_p->k_handle;
646*7c478bd9Sstevel@tonic-gate 	obj_unwrapkey.uk_wrapped_key = (char *)pWrappedKey;
647*7c478bd9Sstevel@tonic-gate 	obj_unwrapkey.uk_wrapped_key_len = ulWrappedKeyLen;
648*7c478bd9Sstevel@tonic-gate 	obj_unwrapkey.uk_count = ulAttributeCount;
649*7c478bd9Sstevel@tonic-gate 
650*7c478bd9Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_UNWRAP_KEY, &obj_unwrapkey)) < 0) {
651*7c478bd9Sstevel@tonic-gate 		if (errno != EINTR)
652*7c478bd9Sstevel@tonic-gate 			break;
653*7c478bd9Sstevel@tonic-gate 	}
654*7c478bd9Sstevel@tonic-gate 	if (r < 0) {
655*7c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
656*7c478bd9Sstevel@tonic-gate 	} else {
657*7c478bd9Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(obj_unwrapkey.uk_return_value);
658*7c478bd9Sstevel@tonic-gate 	}
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate 	free_object_attributes(obj_unwrapkey.uk_attributes, ulAttributeCount);
661*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
662*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
663*7c478bd9Sstevel@tonic-gate 	}
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 	/* Get the CKA_PRIVATE value for the unwrapped key. */
666*7c478bd9Sstevel@tonic-gate 	rv = get_cka_private_value(session_p, obj_unwrapkey.uk_object_handle,
667*7c478bd9Sstevel@tonic-gate 	    &is_pri_obj);
668*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
669*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
670*7c478bd9Sstevel@tonic-gate 	}
671*7c478bd9Sstevel@tonic-gate 
672*7c478bd9Sstevel@tonic-gate 	/*
673*7c478bd9Sstevel@tonic-gate 	 * Store the kernel object handle in the new key object wrapper and
674*7c478bd9Sstevel@tonic-gate 	 * initialize it.
675*7c478bd9Sstevel@tonic-gate 	 */
676*7c478bd9Sstevel@tonic-gate 	new_objp->k_handle = obj_unwrapkey.uk_object_handle;
677*7c478bd9Sstevel@tonic-gate 	new_objp->is_lib_obj = B_FALSE;
678*7c478bd9Sstevel@tonic-gate 	new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
679*7c478bd9Sstevel@tonic-gate 	new_objp->extra_attrlistp = NULL;
680*7c478bd9Sstevel@tonic-gate 
681*7c478bd9Sstevel@tonic-gate 	if (is_pri_obj)
682*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
683*7c478bd9Sstevel@tonic-gate 	else
684*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 	if (is_token_obj)
687*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
688*7c478bd9Sstevel@tonic-gate 	else
689*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
690*7c478bd9Sstevel@tonic-gate 
691*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_objp->object_mutex, NULL);
692*7c478bd9Sstevel@tonic-gate 	new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	/*
695*7c478bd9Sstevel@tonic-gate 	 * Add the new object to the slot's token object list if it is a
696*7c478bd9Sstevel@tonic-gate 	 * a token object. Otherwise, add it to the session's object list.
697*7c478bd9Sstevel@tonic-gate 	 */
698*7c478bd9Sstevel@tonic-gate 	if (is_token_obj) {
699*7c478bd9Sstevel@tonic-gate 		pslot = slot_table[session_p->ses_slotid];
700*7c478bd9Sstevel@tonic-gate 		kernel_add_token_object_to_slot(new_objp, pslot);
701*7c478bd9Sstevel@tonic-gate 	} else {
702*7c478bd9Sstevel@tonic-gate 		kernel_add_object_to_session(new_objp, session_p);
703*7c478bd9Sstevel@tonic-gate 	}
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 	*phKey = (CK_OBJECT_HANDLE)new_objp;
706*7c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
707*7c478bd9Sstevel@tonic-gate 	return (rv);
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate failed_exit:
710*7c478bd9Sstevel@tonic-gate 	if (new_objp != NULL)
711*7c478bd9Sstevel@tonic-gate 		(void) free(new_objp);
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 	if (clear_key_val != NULL)
714*7c478bd9Sstevel@tonic-gate 		(void) free(clear_key_val);
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 	if (newTemplate != NULL)
717*7c478bd9Sstevel@tonic-gate 		(void) free(newTemplate);
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
720*7c478bd9Sstevel@tonic-gate 	return (rv);
721*7c478bd9Sstevel@tonic-gate }
722*7c478bd9Sstevel@tonic-gate 
723*7c478bd9Sstevel@tonic-gate 
724*7c478bd9Sstevel@tonic-gate CK_RV
725*7c478bd9Sstevel@tonic-gate C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
726*7c478bd9Sstevel@tonic-gate     CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
727*7c478bd9Sstevel@tonic-gate     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
728*7c478bd9Sstevel@tonic-gate {
729*7c478bd9Sstevel@tonic-gate 	CK_RV			rv = CKR_OK;
730*7c478bd9Sstevel@tonic-gate 	kernel_session_t	*session_p;
731*7c478bd9Sstevel@tonic-gate 	kernel_object_t		*basekey_p;
732*7c478bd9Sstevel@tonic-gate 	kernel_object_t		*new_objp;
733*7c478bd9Sstevel@tonic-gate 	kernel_slot_t		*pslot;
734*7c478bd9Sstevel@tonic-gate 	boolean_t		ses_lock_held = B_FALSE;
735*7c478bd9Sstevel@tonic-gate 	CK_BBOOL		is_pri_obj;
736*7c478bd9Sstevel@tonic-gate 	CK_BBOOL		is_token_obj = FALSE;
737*7c478bd9Sstevel@tonic-gate 	crypto_mech_type_t	k_mech_type;
738*7c478bd9Sstevel@tonic-gate 	crypto_derive_key_t	obj_dk;
739*7c478bd9Sstevel@tonic-gate 	int r;
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
742*7c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
743*7c478bd9Sstevel@tonic-gate 
744*7c478bd9Sstevel@tonic-gate 	/* Obtain the session pointer. */
745*7c478bd9Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
746*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
747*7c478bd9Sstevel@tonic-gate 		return (rv);
748*7c478bd9Sstevel@tonic-gate 
749*7c478bd9Sstevel@tonic-gate 	if ((pMechanism == NULL) || (phKey == NULL)) {
750*7c478bd9Sstevel@tonic-gate 		rv = CKR_ARGUMENTS_BAD;
751*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
752*7c478bd9Sstevel@tonic-gate 	}
753*7c478bd9Sstevel@tonic-gate 
754*7c478bd9Sstevel@tonic-gate 	if ((pTemplate == NULL && ulAttributeCount != 0) ||
755*7c478bd9Sstevel@tonic-gate 	    (pTemplate != NULL && ulAttributeCount == 0)) {
756*7c478bd9Sstevel@tonic-gate 		rv = CKR_ARGUMENTS_BAD;
757*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
758*7c478bd9Sstevel@tonic-gate 	}
759*7c478bd9Sstevel@tonic-gate 
760*7c478bd9Sstevel@tonic-gate 	/* Obtain the base key object pointer. */
761*7c478bd9Sstevel@tonic-gate 	HANDLE2OBJECT(hBaseKey, basekey_p, rv);
762*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
763*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
764*7c478bd9Sstevel@tonic-gate 	}
765*7c478bd9Sstevel@tonic-gate 
766*7c478bd9Sstevel@tonic-gate 	/* Get the kernel's internal mechanism number. */
767*7c478bd9Sstevel@tonic-gate 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
768*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
769*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
770*7c478bd9Sstevel@tonic-gate 	}
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate 	/* Create an object wrapper in the library for the generated key. */
773*7c478bd9Sstevel@tonic-gate 	new_objp = calloc(1, sizeof (kernel_object_t));
774*7c478bd9Sstevel@tonic-gate 	if (new_objp == NULL) {
775*7c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
776*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
777*7c478bd9Sstevel@tonic-gate 	}
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 	/* Process the attributes */
780*7c478bd9Sstevel@tonic-gate 	rv = process_object_attributes(pTemplate, ulAttributeCount,
781*7c478bd9Sstevel@tonic-gate 	    &obj_dk.dk_attributes, &is_token_obj);
782*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
783*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
784*7c478bd9Sstevel@tonic-gate 	}
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate 	/* Cannot create a token object with a READ-ONLY session. */
787*7c478bd9Sstevel@tonic-gate 	if (is_token_obj && session_p->ses_RO) {
788*7c478bd9Sstevel@tonic-gate 		free_object_attributes(obj_dk.dk_attributes, ulAttributeCount);
789*7c478bd9Sstevel@tonic-gate 		rv = CKR_SESSION_READ_ONLY;
790*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
791*7c478bd9Sstevel@tonic-gate 	}
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 	/* Call the CRYPTO_DERIVE_KEY ioctl */
794*7c478bd9Sstevel@tonic-gate 	obj_dk.dk_session = session_p->k_session;
795*7c478bd9Sstevel@tonic-gate 	obj_dk.dk_mechanism.cm_type = k_mech_type;
796*7c478bd9Sstevel@tonic-gate 	obj_dk.dk_mechanism.cm_param = pMechanism->pParameter;
797*7c478bd9Sstevel@tonic-gate 	obj_dk.dk_mechanism.cm_param_len = pMechanism->ulParameterLen;
798*7c478bd9Sstevel@tonic-gate 	obj_dk.dk_base_key.ck_format = CRYPTO_KEY_REFERENCE;
799*7c478bd9Sstevel@tonic-gate 	obj_dk.dk_base_key.ck_obj_id = basekey_p->k_handle;
800*7c478bd9Sstevel@tonic-gate 	obj_dk.dk_count = ulAttributeCount;
801*7c478bd9Sstevel@tonic-gate 
802*7c478bd9Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_DERIVE_KEY, &obj_dk)) < 0) {
803*7c478bd9Sstevel@tonic-gate 		if (errno != EINTR)
804*7c478bd9Sstevel@tonic-gate 			break;
805*7c478bd9Sstevel@tonic-gate 	}
806*7c478bd9Sstevel@tonic-gate 	if (r < 0) {
807*7c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
808*7c478bd9Sstevel@tonic-gate 	} else {
809*7c478bd9Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(obj_dk.dk_return_value);
810*7c478bd9Sstevel@tonic-gate 	}
811*7c478bd9Sstevel@tonic-gate 
812*7c478bd9Sstevel@tonic-gate 	free_object_attributes(obj_dk.dk_attributes, ulAttributeCount);
813*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
814*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
815*7c478bd9Sstevel@tonic-gate 	}
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 	/* Get the CKA_PRIVATE value for the derived key. */
818*7c478bd9Sstevel@tonic-gate 	rv = get_cka_private_value(session_p, obj_dk.dk_object_handle,
819*7c478bd9Sstevel@tonic-gate 	    &is_pri_obj);
820*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
821*7c478bd9Sstevel@tonic-gate 		goto failed_exit;
822*7c478bd9Sstevel@tonic-gate 	}
823*7c478bd9Sstevel@tonic-gate 
824*7c478bd9Sstevel@tonic-gate 	/*
825*7c478bd9Sstevel@tonic-gate 	 * Store the kernel object handle into the new derived key object
826*7c478bd9Sstevel@tonic-gate 	 * and finish the object initialization.
827*7c478bd9Sstevel@tonic-gate 	 */
828*7c478bd9Sstevel@tonic-gate 	new_objp->is_lib_obj = B_FALSE;
829*7c478bd9Sstevel@tonic-gate 	new_objp->k_handle = obj_dk.dk_object_handle;
830*7c478bd9Sstevel@tonic-gate 	new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
831*7c478bd9Sstevel@tonic-gate 	new_objp->extra_attrlistp = NULL;
832*7c478bd9Sstevel@tonic-gate 
833*7c478bd9Sstevel@tonic-gate 	if (is_pri_obj)
834*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
835*7c478bd9Sstevel@tonic-gate 	else
836*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate 	if (is_token_obj)
839*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
840*7c478bd9Sstevel@tonic-gate 	else
841*7c478bd9Sstevel@tonic-gate 		new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
842*7c478bd9Sstevel@tonic-gate 
843*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_objp->object_mutex, NULL);
844*7c478bd9Sstevel@tonic-gate 	new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
845*7c478bd9Sstevel@tonic-gate 
846*7c478bd9Sstevel@tonic-gate 	/*
847*7c478bd9Sstevel@tonic-gate 	 * Add the new derived object to the slot's token list if it is a
848*7c478bd9Sstevel@tonic-gate 	 * token object. Otherwise, add it to the session's object list.
849*7c478bd9Sstevel@tonic-gate 	 */
850*7c478bd9Sstevel@tonic-gate 	if (is_token_obj) {
851*7c478bd9Sstevel@tonic-gate 		pslot = slot_table[session_p->ses_slotid];
852*7c478bd9Sstevel@tonic-gate 		kernel_add_token_object_to_slot(new_objp, pslot);
853*7c478bd9Sstevel@tonic-gate 	} else {
854*7c478bd9Sstevel@tonic-gate 		kernel_add_object_to_session(new_objp, session_p);
855*7c478bd9Sstevel@tonic-gate 	}
856*7c478bd9Sstevel@tonic-gate 
857*7c478bd9Sstevel@tonic-gate 	*phKey = (CK_OBJECT_HANDLE)new_objp;
858*7c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
859*7c478bd9Sstevel@tonic-gate 	return (rv);
860*7c478bd9Sstevel@tonic-gate 
861*7c478bd9Sstevel@tonic-gate failed_exit:
862*7c478bd9Sstevel@tonic-gate 	if (new_objp != NULL) {
863*7c478bd9Sstevel@tonic-gate 		(void) free(new_objp);
864*7c478bd9Sstevel@tonic-gate 	}
865*7c478bd9Sstevel@tonic-gate 
866*7c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
867*7c478bd9Sstevel@tonic-gate 	return (rv);
868*7c478bd9Sstevel@tonic-gate }
869