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
5034448feSmcpowers * Common Development and Distribution License (the "License").
6034448feSmcpowers * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*77e5e96bSMark Powers * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <strings.h>
277c478bd9Sstevel@tonic-gate #include <errno.h>
28f9fbec18Smcpowers #include <ecc_impl.h>
297c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
307c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h>
317c478bd9Sstevel@tonic-gate #include "kernelGlobal.h"
327c478bd9Sstevel@tonic-gate #include "kernelSession.h"
337c478bd9Sstevel@tonic-gate #include "kernelObject.h"
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate static boolean_t
attribute_in_template(CK_ATTRIBUTE_TYPE type,CK_ATTRIBUTE_PTR t,CK_ULONG cnt)36034448feSmcpowers attribute_in_template(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR t, CK_ULONG cnt)
37034448feSmcpowers {
38034448feSmcpowers int i;
39034448feSmcpowers
40034448feSmcpowers for (i = 0; i < cnt; i++) {
41034448feSmcpowers if (t[i].type == type)
42034448feSmcpowers return (B_TRUE);
43034448feSmcpowers }
44034448feSmcpowers return (B_FALSE);
45034448feSmcpowers }
46034448feSmcpowers
47034448feSmcpowers /*
48034448feSmcpowers * This routine returns modulus bytes rounded up to the nearest 8 byte
49034448feSmcpowers * chunk. This is so we don't have to pass in max sized buffers for
50034448feSmcpowers * returned attributes. Every unnecessary byte that we pass in results
51034448feSmcpowers * in a kernel allocation.
52034448feSmcpowers */
53034448feSmcpowers static ulong_t
get_modulus_bytes(CK_ATTRIBUTE_PTR t,CK_ULONG cnt)54034448feSmcpowers get_modulus_bytes(CK_ATTRIBUTE_PTR t, CK_ULONG cnt)
55034448feSmcpowers {
56034448feSmcpowers CK_ULONG modulus_len;
57034448feSmcpowers int i;
58034448feSmcpowers
59034448feSmcpowers for (i = 0; i < cnt; i++) {
60034448feSmcpowers if (t[i].type == CKA_MODULUS_BITS) {
61034448feSmcpowers get_ulong_attr_from_template(&modulus_len, &t[i]);
62034448feSmcpowers /* convert from bit length to byte length */
63034448feSmcpowers modulus_len = (modulus_len - 1) / 64 + 1;
64034448feSmcpowers return (modulus_len * 8);
65034448feSmcpowers }
66034448feSmcpowers }
67034448feSmcpowers return (0);
68034448feSmcpowers }
69034448feSmcpowers
70034448feSmcpowers /*
71034448feSmcpowers * Remove specified attribute from array. Storage for the attribute's
72034448feSmcpowers * value is freed if 'free_attr' is TRUE. Attributes are shifted so they are
73034448feSmcpowers * contiguous within the array, i.e. the next attribute is shifted into
74034448feSmcpowers * the position of the removed attribute. Returns TRUE if specified
75034448feSmcpowers * attribute is removed.
76034448feSmcpowers */
77034448feSmcpowers static boolean_t
remove_one_attribute(CK_ATTRIBUTE_PTR t,CK_ULONG type,uint_t count,boolean_t free_attr)78034448feSmcpowers remove_one_attribute(CK_ATTRIBUTE_PTR t, CK_ULONG type, uint_t count,
79034448feSmcpowers boolean_t free_attr)
80034448feSmcpowers {
81034448feSmcpowers int i, j;
82034448feSmcpowers
83034448feSmcpowers for (i = 0, j = 0; i < count; i++) {
84034448feSmcpowers if (t[i].type == type) {
85034448feSmcpowers if (free_attr) {
86034448feSmcpowers free(t[i].pValue);
87034448feSmcpowers }
88034448feSmcpowers continue;
89034448feSmcpowers }
90034448feSmcpowers if (i != j) {
91034448feSmcpowers t[j].type = t[i].type;
92034448feSmcpowers t[j].pValue = t[i].pValue;
93034448feSmcpowers t[j].ulValueLen = t[i].ulValueLen;
94034448feSmcpowers }
95034448feSmcpowers j++;
96034448feSmcpowers }
97034448feSmcpowers if (j == count)
98034448feSmcpowers return (B_FALSE);
99034448feSmcpowers
100034448feSmcpowers /* safety */
101034448feSmcpowers t[j].pValue = NULL;
102034448feSmcpowers t[j].ulValueLen = 0;
103034448feSmcpowers return (B_TRUE);
104034448feSmcpowers }
105034448feSmcpowers
106034448feSmcpowers static boolean_t
is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount)1077c478bd9Sstevel@tonic-gate is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate int i;
1107c478bd9Sstevel@tonic-gate for (i = 0; i < ulAttributeCount; i++) {
1117c478bd9Sstevel@tonic-gate if (pTemplate[i].type == CKA_CLASS &&
1127c478bd9Sstevel@tonic-gate *(CK_OBJECT_CLASS *)(pTemplate[i].pValue) ==
1137c478bd9Sstevel@tonic-gate CKO_SECRET_KEY)
1147c478bd9Sstevel@tonic-gate return (B_TRUE);
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate return (B_FALSE);
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate
119034448feSmcpowers /*
120034448feSmcpowers * Allocate a template with space for new_count entries and copy the
121034448feSmcpowers * specified template into the new template.
122034448feSmcpowers */
123034448feSmcpowers static CK_ATTRIBUTE_PTR
grow_template(CK_ATTRIBUTE_PTR old_template,CK_ULONG old_count,CK_ULONG new_count)124034448feSmcpowers grow_template(CK_ATTRIBUTE_PTR old_template, CK_ULONG old_count,
125034448feSmcpowers CK_ULONG new_count)
126034448feSmcpowers {
127034448feSmcpowers CK_ATTRIBUTE_PTR new_template;
128034448feSmcpowers
129034448feSmcpowers new_template = malloc(new_count * sizeof (CK_ATTRIBUTE));
130034448feSmcpowers if (new_template != NULL)
131034448feSmcpowers bcopy(old_template, new_template,
132034448feSmcpowers old_count * sizeof (CK_ATTRIBUTE));
133034448feSmcpowers return (new_template);
134034448feSmcpowers }
135034448feSmcpowers
136034448feSmcpowers /*
137034448feSmcpowers * For fixed length keys such as DES, return the length based on
138034448feSmcpowers * the key type. For variable length keys such as AES, take the
139034448feSmcpowers * length from the CKA_VALUE_LEN attribute.
140034448feSmcpowers */
141034448feSmcpowers static int
get_key_len_from_template(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,kernel_object_t * basekey_p,ulong_t * key_len)142034448feSmcpowers get_key_len_from_template(CK_MECHANISM_PTR pMechanism,
143034448feSmcpowers CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
144034448feSmcpowers kernel_object_t *basekey_p, ulong_t *key_len)
145034448feSmcpowers {
146034448feSmcpowers boolean_t fixed_len_key = B_FALSE;
147034448feSmcpowers ulong_t key_type;
148034448feSmcpowers int i;
149034448feSmcpowers
150034448feSmcpowers for (i = 0; i < ulAttributeCount; i++) {
151034448feSmcpowers if (pTemplate[i].type == CKA_KEY_TYPE) {
152034448feSmcpowers get_ulong_attr_from_template(&key_type, &pTemplate[i]);
153034448feSmcpowers break;
154034448feSmcpowers }
155034448feSmcpowers }
156034448feSmcpowers /* CKA_KEY_TYPE must be present */
157034448feSmcpowers if (i == ulAttributeCount)
158034448feSmcpowers return (CKR_TEMPLATE_INCOMPLETE);
159034448feSmcpowers
160034448feSmcpowers switch (key_type) {
161034448feSmcpowers case CKK_DES:
162034448feSmcpowers *key_len = 8;
163034448feSmcpowers fixed_len_key = B_TRUE;
164034448feSmcpowers break;
165034448feSmcpowers case CKK_DES3:
166034448feSmcpowers *key_len = 24;
167034448feSmcpowers fixed_len_key = B_TRUE;
168034448feSmcpowers break;
169034448feSmcpowers case CKK_AES:
170034448feSmcpowers case CKK_BLOWFISH:
171034448feSmcpowers for (i = 0; i < ulAttributeCount; i++) {
172034448feSmcpowers if (pTemplate[i].type == CKA_VALUE_LEN) {
173034448feSmcpowers get_ulong_attr_from_template(key_len,
174034448feSmcpowers &pTemplate[i]);
175034448feSmcpowers break;
176034448feSmcpowers }
177034448feSmcpowers }
178034448feSmcpowers /* CKA_VALUE_LEN must be present */
179034448feSmcpowers if (i == ulAttributeCount)
180034448feSmcpowers return (CKR_TEMPLATE_INCOMPLETE);
181034448feSmcpowers break;
182034448feSmcpowers case CKK_GENERIC_SECRET:
183034448feSmcpowers /*
184034448feSmcpowers * The key will not be truncated, so we need to
185034448feSmcpowers * get the max length for the mechanism.
186034448feSmcpowers */
187034448feSmcpowers if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE) {
188034448feSmcpowers CK_ATTRIBUTE tmp;
189034448feSmcpowers
190034448feSmcpowers tmp.type = CKA_PRIME;
191034448feSmcpowers tmp.pValue = NULL;
192034448feSmcpowers
193034448feSmcpowers /* get size of attribute */
194034448feSmcpowers if (kernel_get_attribute(basekey_p, &tmp) != CKR_OK) {
195034448feSmcpowers return (CKR_ARGUMENTS_BAD);
196034448feSmcpowers }
197034448feSmcpowers *key_len = tmp.ulValueLen;
198ef39737bSmcpowers } else if (pMechanism->mechanism == CKM_ECDH1_DERIVE) {
199f9fbec18Smcpowers *key_len = EC_MAX_VALUE_LEN;
200034448feSmcpowers } else {
201034448feSmcpowers return (CKR_ARGUMENTS_BAD);
202034448feSmcpowers }
203034448feSmcpowers break;
204034448feSmcpowers default:
205034448feSmcpowers return (CKR_ATTRIBUTE_VALUE_INVALID);
206034448feSmcpowers }
207034448feSmcpowers
208034448feSmcpowers if (fixed_len_key && attribute_in_template(CKA_VALUE_LEN,
209034448feSmcpowers pTemplate, ulAttributeCount))
210034448feSmcpowers return (CKR_TEMPLATE_INCONSISTENT);
211034448feSmcpowers
212034448feSmcpowers return (CKR_OK);
213034448feSmcpowers }
214034448feSmcpowers
215034448feSmcpowers /* find specified attribute src template and copy to dest */
216034448feSmcpowers static int
copy_attribute(CK_ULONG type,CK_ATTRIBUTE_PTR src,CK_ULONG src_cnt,CK_ATTRIBUTE_PTR dst)217034448feSmcpowers copy_attribute(CK_ULONG type, CK_ATTRIBUTE_PTR src, CK_ULONG src_cnt,
218034448feSmcpowers CK_ATTRIBUTE_PTR dst)
219034448feSmcpowers {
220034448feSmcpowers int rv, i;
221034448feSmcpowers
222034448feSmcpowers for (i = 0; i < src_cnt; i++) {
223034448feSmcpowers if (src[i].type == type) {
224034448feSmcpowers rv = get_string_from_template(dst, &src[i]);
225034448feSmcpowers break;
226034448feSmcpowers }
227034448feSmcpowers }
228034448feSmcpowers /*
229034448feSmcpowers * The public template didn't have attribute.
230034448feSmcpowers */
231034448feSmcpowers if (i == src_cnt) {
232034448feSmcpowers rv = CKR_TEMPLATE_INCOMPLETE;
233034448feSmcpowers }
234034448feSmcpowers return (rv);
235034448feSmcpowers }
236034448feSmcpowers
237034448feSmcpowers static void
free_attributes(caddr_t p,uint_t * countp)238034448feSmcpowers free_attributes(caddr_t p, uint_t *countp)
239034448feSmcpowers {
240034448feSmcpowers if (*countp > 0) {
241034448feSmcpowers free_object_attributes(p, *countp);
242034448feSmcpowers *countp = 0;
243034448feSmcpowers }
244034448feSmcpowers }
245034448feSmcpowers
246034448feSmcpowers CK_RV
key_gen_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_objp)247034448feSmcpowers key_gen_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate,
248034448feSmcpowers CK_ULONG ulCount, kernel_session_t *session_p,
249034448feSmcpowers crypto_mech_type_t k_mech_type, kernel_object_t *new_objp)
250034448feSmcpowers {
251034448feSmcpowers crypto_nostore_generate_key_t obj_ngk;
252034448feSmcpowers char *key_buf = NULL;
253034448feSmcpowers CK_ATTRIBUTE_PTR newTemplate = NULL;
254034448feSmcpowers CK_BBOOL is_token_obj = FALSE;
255034448feSmcpowers CK_RV rv = CKR_OK;
256034448feSmcpowers ulong_t key_len = 0;
257034448feSmcpowers uint_t attr_count;
258034448feSmcpowers int r;
259034448feSmcpowers
260034448feSmcpowers obj_ngk.ngk_in_count = 0;
261034448feSmcpowers obj_ngk.ngk_out_count = 0;
262034448feSmcpowers
263034448feSmcpowers rv = get_key_len_from_template(pMechanism, pTemplate, ulCount,
264034448feSmcpowers NULL, &key_len);
265034448feSmcpowers if (rv != CRYPTO_SUCCESS)
266034448feSmcpowers goto failed_exit;
267034448feSmcpowers
268034448feSmcpowers if ((key_buf = malloc(key_len)) == NULL) {
269034448feSmcpowers rv = CKR_HOST_MEMORY;
270034448feSmcpowers goto failed_exit;
271034448feSmcpowers }
272034448feSmcpowers
273034448feSmcpowers attr_count = ulCount + 1;
274034448feSmcpowers newTemplate = grow_template(pTemplate, ulCount, attr_count);
275034448feSmcpowers if (newTemplate == NULL) {
276034448feSmcpowers rv = CKR_HOST_MEMORY;
277034448feSmcpowers goto failed_exit;
278034448feSmcpowers }
279034448feSmcpowers
280034448feSmcpowers /* Now add the CKA_VALUE attribute to template */
281034448feSmcpowers newTemplate[ulCount].type = CKA_VALUE;
282034448feSmcpowers newTemplate[ulCount].pValue = (caddr_t)key_buf;
283034448feSmcpowers newTemplate[ulCount].ulValueLen = key_len;
284034448feSmcpowers
285034448feSmcpowers rv = process_object_attributes(newTemplate, attr_count - 1,
286034448feSmcpowers &obj_ngk.ngk_in_attributes, &is_token_obj);
287034448feSmcpowers if (rv != CKR_OK) {
288034448feSmcpowers goto failed_exit;
289034448feSmcpowers }
290034448feSmcpowers rv = process_object_attributes(&newTemplate[ulCount],
291034448feSmcpowers 1, &obj_ngk.ngk_out_attributes, &is_token_obj);
292034448feSmcpowers if (rv != CKR_OK) {
293034448feSmcpowers goto failed_exit;
294034448feSmcpowers }
295034448feSmcpowers
296034448feSmcpowers /* Cannot create a token object with a READ-ONLY session. */
297034448feSmcpowers if (is_token_obj && session_p->ses_RO) {
298034448feSmcpowers rv = CKR_SESSION_READ_ONLY;
299034448feSmcpowers goto failed_exit;
300034448feSmcpowers }
301034448feSmcpowers
302034448feSmcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY ioctl */
303034448feSmcpowers obj_ngk.ngk_session = session_p->k_session;
304034448feSmcpowers obj_ngk.ngk_in_count = attr_count - 1;
305034448feSmcpowers obj_ngk.ngk_out_count = 1;
306034448feSmcpowers obj_ngk.ngk_mechanism.cm_type = k_mech_type;
307034448feSmcpowers obj_ngk.ngk_mechanism.cm_param = pMechanism->pParameter;
308034448feSmcpowers obj_ngk.ngk_mechanism.cm_param_len = pMechanism->ulParameterLen;
309034448feSmcpowers
310034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY,
311034448feSmcpowers &obj_ngk)) < 0) {
312034448feSmcpowers if (errno != EINTR)
313034448feSmcpowers break;
314034448feSmcpowers }
315034448feSmcpowers if (r < 0) {
316034448feSmcpowers rv = CKR_FUNCTION_FAILED;
317034448feSmcpowers } else {
318034448feSmcpowers rv = crypto2pkcs11_error_number(obj_ngk.ngk_return_value);
319034448feSmcpowers }
320034448feSmcpowers free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count);
321034448feSmcpowers if (rv != CKR_OK) {
322034448feSmcpowers goto failed_exit;
323034448feSmcpowers }
324034448feSmcpowers
325034448feSmcpowers rv = get_object_attributes(&newTemplate[ulCount], 1,
326034448feSmcpowers obj_ngk.ngk_out_attributes);
327034448feSmcpowers free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count);
328034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
329034448feSmcpowers goto failed_exit;
330034448feSmcpowers }
331034448feSmcpowers
332034448feSmcpowers /*
333034448feSmcpowers * CKA_VALUE_LEN is not stored with the secret key object,
334034448feSmcpowers * so we remove it by shifting attributes down one.
335034448feSmcpowers */
336034448feSmcpowers (void) remove_one_attribute(newTemplate, CKA_VALUE_LEN,
337034448feSmcpowers attr_count, B_FALSE);
338034448feSmcpowers
339034448feSmcpowers rv = kernel_build_object(newTemplate, attr_count - 1,
340034448feSmcpowers new_objp, session_p, KERNEL_GEN_KEY);
341034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
342034448feSmcpowers goto failed_exit;
343034448feSmcpowers }
344034448feSmcpowers new_objp->is_lib_obj = B_TRUE;
345034448feSmcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
346034448feSmcpowers (void) free(newTemplate);
347034448feSmcpowers bzero(key_buf, key_len);
348034448feSmcpowers (void) free(key_buf);
349034448feSmcpowers return (CKR_OK);
350034448feSmcpowers
351034448feSmcpowers failed_exit:
352034448feSmcpowers free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count);
353034448feSmcpowers free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count);
354034448feSmcpowers if (key_buf != NULL) {
355034448feSmcpowers bzero(key_buf, key_len);
356034448feSmcpowers (void) free(key_buf);
357034448feSmcpowers }
358034448feSmcpowers if (newTemplate != NULL) {
359034448feSmcpowers (void) free(newTemplate);
360034448feSmcpowers }
361034448feSmcpowers return (rv);
362034448feSmcpowers }
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate CK_RV
C_GenerateKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phKey)3657c478bd9Sstevel@tonic-gate C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
3667c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
3677c478bd9Sstevel@tonic-gate {
3687c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
3697c478bd9Sstevel@tonic-gate kernel_session_t *session_p;
3707c478bd9Sstevel@tonic-gate kernel_object_t *new_objp = NULL;
3717c478bd9Sstevel@tonic-gate kernel_slot_t *pslot;
3727c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE;
3737c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj;
3747c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE;
3757c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type;
3767c478bd9Sstevel@tonic-gate int r;
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate if (!kernel_initialized)
3797c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate /* Obtain the session pointer */
3827c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
3837c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
3847c478bd9Sstevel@tonic-gate return (rv);
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate if ((pMechanism == NULL) || (phKey == NULL)) {
3877c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
3887c478bd9Sstevel@tonic-gate goto failed_exit;
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate if ((pTemplate == NULL) && (ulCount != 0)) {
3927c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
3937c478bd9Sstevel@tonic-gate goto failed_exit;
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */
3977c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
3987c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
3997c478bd9Sstevel@tonic-gate goto failed_exit;
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate /* Create an object wrapper in the library first */
4037c478bd9Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t));
4047c478bd9Sstevel@tonic-gate if (new_objp == NULL) {
4057c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
4067c478bd9Sstevel@tonic-gate goto failed_exit;
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate
409034448feSmcpowers /*
410034448feSmcpowers * Special Case: if token does not support object creation,
411034448feSmcpowers * but does support key generation by value, then create a session
412034448feSmcpowers * object and initialize with value returned by token.
413034448feSmcpowers */
414034448feSmcpowers pslot = slot_table[session_p->ses_slotid];
415034448feSmcpowers if (!pslot->sl_func_list.fl_object_create) {
416034448feSmcpowers rv = key_gen_by_value(pMechanism, pTemplate, ulCount, session_p,
417034448feSmcpowers k_mech_type, new_objp);
418034448feSmcpowers if (rv != CKR_OK)
419034448feSmcpowers goto failed_exit;
420034448feSmcpowers } else {
421034448feSmcpowers crypto_object_generate_key_t obj_gk;
422034448feSmcpowers
4237c478bd9Sstevel@tonic-gate /* Process the attributes */
4247c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulCount,
4257c478bd9Sstevel@tonic-gate &obj_gk.gk_attributes, &is_token_obj);
4267c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
4277c478bd9Sstevel@tonic-gate goto failed_exit;
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */
4307c478bd9Sstevel@tonic-gate if (is_token_obj && session_p->ses_RO) {
4317c478bd9Sstevel@tonic-gate free_object_attributes(obj_gk.gk_attributes, ulCount);
4327c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY;
4337c478bd9Sstevel@tonic-gate goto failed_exit;
4347c478bd9Sstevel@tonic-gate }
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate /* Call the CRYPTO_GENERATE_KEY ioctl */
4377c478bd9Sstevel@tonic-gate obj_gk.gk_session = session_p->k_session;
4387c478bd9Sstevel@tonic-gate obj_gk.gk_count = ulCount;
4397c478bd9Sstevel@tonic-gate obj_gk.gk_mechanism.cm_type = k_mech_type;
4407c478bd9Sstevel@tonic-gate obj_gk.gk_mechanism.cm_param = pMechanism->pParameter;
4417c478bd9Sstevel@tonic-gate obj_gk.gk_mechanism.cm_param_len = pMechanism->ulParameterLen;
4427c478bd9Sstevel@tonic-gate
443034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY,
444034448feSmcpowers &obj_gk)) < 0) {
4457c478bd9Sstevel@tonic-gate if (errno != EINTR)
4467c478bd9Sstevel@tonic-gate break;
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate if (r < 0) {
4497c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
4507c478bd9Sstevel@tonic-gate } else {
4517c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_gk.gk_return_value);
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate free_object_attributes(obj_gk.gk_attributes, ulCount);
455034448feSmcpowers
4567c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
4577c478bd9Sstevel@tonic-gate goto failed_exit;
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate /* Get the value of the CKA_PRIVATE attribute. */
461034448feSmcpowers rv = get_cka_private_value(session_p, obj_gk.gk_handle,
462034448feSmcpowers &is_pri_obj);
4637c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
4647c478bd9Sstevel@tonic-gate goto failed_exit;
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate /*
4687c478bd9Sstevel@tonic-gate * Store the kernel object handle in the object wrapper and
4697c478bd9Sstevel@tonic-gate * initialize the library object.
4707c478bd9Sstevel@tonic-gate */
4717c478bd9Sstevel@tonic-gate new_objp->k_handle = obj_gk.gk_handle;
4727c478bd9Sstevel@tonic-gate new_objp->is_lib_obj = B_FALSE;
4737c478bd9Sstevel@tonic-gate new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
4747c478bd9Sstevel@tonic-gate new_objp->extra_attrlistp = NULL;
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate if (is_pri_obj)
4777c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
4787c478bd9Sstevel@tonic-gate else
4797c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
4807c478bd9Sstevel@tonic-gate
4817c478bd9Sstevel@tonic-gate if (is_token_obj)
4827c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
4837c478bd9Sstevel@tonic-gate else
4847c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
485034448feSmcpowers }
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
4887c478bd9Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate /*
4917c478bd9Sstevel@tonic-gate * Add the new object to the slot's token object list if it is a
4927c478bd9Sstevel@tonic-gate * a token object. Otherwise, add it to the session's object list.
4937c478bd9Sstevel@tonic-gate */
4947c478bd9Sstevel@tonic-gate if (is_token_obj) {
4957c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid];
4967c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot);
4977c478bd9Sstevel@tonic-gate } else {
4987c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p);
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp;
5027c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
5037c478bd9Sstevel@tonic-gate return (rv);
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate failed_exit:
5067c478bd9Sstevel@tonic-gate if (new_objp != NULL) {
5077c478bd9Sstevel@tonic-gate (void) free(new_objp);
5087c478bd9Sstevel@tonic-gate }
5097c478bd9Sstevel@tonic-gate
5107c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
5117c478bd9Sstevel@tonic-gate return (rv);
5127c478bd9Sstevel@tonic-gate }
5137c478bd9Sstevel@tonic-gate
514034448feSmcpowers CK_RV
key_gen_rsa_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_pub_objp,kernel_object_t * new_pri_objp)515034448feSmcpowers key_gen_rsa_by_value(CK_MECHANISM_PTR pMechanism,
516034448feSmcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
517034448feSmcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
518034448feSmcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type,
519034448feSmcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp)
520034448feSmcpowers {
521034448feSmcpowers crypto_nostore_generate_key_pair_t obj_nkp;
522034448feSmcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL;
523034448feSmcpowers CK_ATTRIBUTE_PTR priTemplate = NULL;
524034448feSmcpowers CK_RV rv = CKR_OK;
525034448feSmcpowers CK_BBOOL is_token_obj1 = FALSE;
526034448feSmcpowers CK_BBOOL is_token_obj2 = FALSE;
527034448feSmcpowers uint_t pub_attr_count, pri_attr_count;
528034448feSmcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0;
529034448feSmcpowers char public_modulus[512];
530034448feSmcpowers char public_exponent[8];
531034448feSmcpowers char private_exponent[512];
532034448feSmcpowers char private_modulus[512];
533034448feSmcpowers char prime_1[512];
534034448feSmcpowers char prime_2[512];
535034448feSmcpowers char exponent_1[512];
536034448feSmcpowers char exponent_2[512];
537034448feSmcpowers char coefficient[512];
538034448feSmcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY;
539034448feSmcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY;
540034448feSmcpowers CK_ULONG key_type;
541034448feSmcpowers CK_ULONG modulus_bytes;
542034448feSmcpowers boolean_t has_class, has_key_type, has_pub_exponent;
543034448feSmcpowers int n, r;
544034448feSmcpowers
545034448feSmcpowers obj_nkp.nkp_in_public_count = 0;
546034448feSmcpowers obj_nkp.nkp_out_public_count = 0;
547034448feSmcpowers obj_nkp.nkp_in_private_count = 0;
548034448feSmcpowers obj_nkp.nkp_out_private_count = 0;
549034448feSmcpowers
550034448feSmcpowers /* modulus bits must be present when generating a RSA key pair */
551034448feSmcpowers if (!attribute_in_template(CKA_MODULUS_BITS, pPublicKeyTemplate,
552034448feSmcpowers ulPublicKeyAttributeCount)) {
553034448feSmcpowers rv = CKR_TEMPLATE_INCOMPLETE;
554034448feSmcpowers goto failed_exit;
555034448feSmcpowers }
556034448feSmcpowers
557034448feSmcpowers modulus_bytes = get_modulus_bytes(pPublicKeyTemplate,
558034448feSmcpowers ulPublicKeyAttributeCount);
559034448feSmcpowers
560034448feSmcpowers /*
561034448feSmcpowers * Add CKA_MODULUS to the public template.
562034448feSmcpowers * This attribute must not be in the template.
563034448feSmcpowers */
564034448feSmcpowers if (attribute_in_template(CKA_MODULUS, pPublicKeyTemplate,
565034448feSmcpowers ulPublicKeyAttributeCount)) {
566034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT;
567034448feSmcpowers goto failed_exit;
568034448feSmcpowers }
569034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate,
570034448feSmcpowers ulPublicKeyAttributeCount);
571034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate,
572034448feSmcpowers ulPublicKeyAttributeCount);
573034448feSmcpowers has_pub_exponent = attribute_in_template(CKA_PUBLIC_EXPONENT,
574034448feSmcpowers pPublicKeyTemplate, ulPublicKeyAttributeCount);
575034448feSmcpowers
576034448feSmcpowers pub_attr_count = ulPublicKeyAttributeCount + 1;
577034448feSmcpowers if (!has_class)
578034448feSmcpowers pub_attr_count++;
579034448feSmcpowers if (!has_key_type)
580034448feSmcpowers pub_attr_count++;
581034448feSmcpowers if (!has_pub_exponent)
582034448feSmcpowers pub_attr_count++;
583034448feSmcpowers pubTemplate = grow_template(pPublicKeyTemplate,
584034448feSmcpowers ulPublicKeyAttributeCount, pub_attr_count);
585034448feSmcpowers if (pubTemplate == NULL) {
586034448feSmcpowers rv = CKR_HOST_MEMORY;
587034448feSmcpowers goto failed_exit;
588034448feSmcpowers }
589034448feSmcpowers
590034448feSmcpowers n = ulPublicKeyAttributeCount;
591034448feSmcpowers if (!has_class) {
592034448feSmcpowers pubTemplate[n].type = CKA_CLASS;
593034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&pub_class;
594034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (pub_class);
595034448feSmcpowers n++;
596034448feSmcpowers }
597034448feSmcpowers if (!has_key_type) {
598034448feSmcpowers pubTemplate[n].type = CKA_KEY_TYPE;
599034448feSmcpowers key_type = CKK_RSA;
600034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&key_type;
601034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (key_type);
602034448feSmcpowers n++;
603034448feSmcpowers }
604034448feSmcpowers if (!has_pub_exponent) {
605034448feSmcpowers pubTemplate[n].type = CKA_PUBLIC_EXPONENT;
606034448feSmcpowers pubTemplate[n].pValue = (caddr_t)public_exponent;
607034448feSmcpowers pubTemplate[n].ulValueLen = modulus_bytes;
608034448feSmcpowers n++;
609034448feSmcpowers pub_out_attr_count++;
610034448feSmcpowers }
611034448feSmcpowers pubTemplate[n].type = CKA_MODULUS;
612034448feSmcpowers pubTemplate[n].pValue = (caddr_t)public_modulus;
613034448feSmcpowers pubTemplate[n].ulValueLen = modulus_bytes;
614034448feSmcpowers pub_out_attr_count++;
615034448feSmcpowers
616034448feSmcpowers rv = process_object_attributes(pubTemplate,
617034448feSmcpowers pub_attr_count - pub_out_attr_count,
618034448feSmcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1);
619034448feSmcpowers if (rv != CKR_OK) {
620034448feSmcpowers goto failed_exit;
621034448feSmcpowers }
622034448feSmcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count;
623034448feSmcpowers
624034448feSmcpowers rv = process_object_attributes(
625034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
626034448feSmcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes,
627034448feSmcpowers &is_token_obj1);
628034448feSmcpowers if (rv != CKR_OK) {
629034448feSmcpowers goto failed_exit;
630034448feSmcpowers }
631034448feSmcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count;
632034448feSmcpowers
633034448feSmcpowers /*
634034448feSmcpowers * Cannot create a token object with a READ-ONLY
635034448feSmcpowers * session.
636034448feSmcpowers */
637034448feSmcpowers if (is_token_obj1 && session_p->ses_RO) {
638034448feSmcpowers rv = CKR_SESSION_READ_ONLY;
639034448feSmcpowers goto failed_exit;
640034448feSmcpowers }
641034448feSmcpowers
642034448feSmcpowers /*
643034448feSmcpowers * Add CKA_MODULUS and CKA_PRIVATE_EXPONENT
644034448feSmcpowers * to the private template. These attributes
645034448feSmcpowers * must not be in the template.
646034448feSmcpowers */
647034448feSmcpowers if (attribute_in_template(CKA_PRIVATE_EXPONENT,
648034448feSmcpowers pPrivateKeyTemplate, ulPrivateKeyAttributeCount) ||
649034448feSmcpowers attribute_in_template(CKA_MODULUS,
650034448feSmcpowers pPrivateKeyTemplate, ulPrivateKeyAttributeCount)) {
651034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT;
652034448feSmcpowers goto failed_exit;
653034448feSmcpowers }
654034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate,
655034448feSmcpowers ulPrivateKeyAttributeCount);
656034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate,
657034448feSmcpowers ulPrivateKeyAttributeCount);
658034448feSmcpowers
659034448feSmcpowers pri_attr_count = ulPrivateKeyAttributeCount + 7;
660034448feSmcpowers if (!has_class)
661034448feSmcpowers pri_attr_count++;
662034448feSmcpowers if (!has_key_type)
663034448feSmcpowers pri_attr_count++;
664034448feSmcpowers
665034448feSmcpowers /* allocate space for CKA_PUBLIC_EXPONENT */
666034448feSmcpowers priTemplate = grow_template(pPrivateKeyTemplate,
667034448feSmcpowers ulPrivateKeyAttributeCount, pri_attr_count + 1);
668034448feSmcpowers if (priTemplate == NULL) {
669034448feSmcpowers rv = CKR_HOST_MEMORY;
670034448feSmcpowers goto failed_exit;
671034448feSmcpowers }
672034448feSmcpowers n = ulPrivateKeyAttributeCount;
673034448feSmcpowers if (!has_class) {
674034448feSmcpowers priTemplate[n].type = CKA_CLASS;
675034448feSmcpowers priTemplate[n].pValue = (caddr_t)&pri_class;
676034448feSmcpowers priTemplate[n].ulValueLen = sizeof (pri_class);
677034448feSmcpowers n++;
678034448feSmcpowers }
679034448feSmcpowers if (!has_key_type) {
680034448feSmcpowers priTemplate[n].type = CKA_KEY_TYPE;
681034448feSmcpowers key_type = CKK_RSA;
682034448feSmcpowers priTemplate[n].pValue = (caddr_t)&key_type;
683034448feSmcpowers priTemplate[n].ulValueLen = sizeof (key_type);
684034448feSmcpowers n++;
685034448feSmcpowers }
686034448feSmcpowers priTemplate[n].type = CKA_MODULUS;
687034448feSmcpowers priTemplate[n].pValue = (caddr_t)private_modulus;
688034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes;
689034448feSmcpowers pri_out_attr_count++;
690034448feSmcpowers
691034448feSmcpowers n++;
692034448feSmcpowers priTemplate[n].type = CKA_PRIVATE_EXPONENT;
693034448feSmcpowers priTemplate[n].pValue = (caddr_t)private_exponent;
694034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes;
695034448feSmcpowers pri_out_attr_count++;
696034448feSmcpowers
697034448feSmcpowers n++;
698034448feSmcpowers priTemplate[n].type = CKA_PRIME_1;
699034448feSmcpowers priTemplate[n].pValue = (caddr_t)prime_1;
700034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes/2;
701034448feSmcpowers pri_out_attr_count++;
702034448feSmcpowers
703034448feSmcpowers n++;
704034448feSmcpowers priTemplate[n].type = CKA_PRIME_2;
705034448feSmcpowers priTemplate[n].pValue = (caddr_t)prime_2;
706034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes/2;
707034448feSmcpowers pri_out_attr_count++;
708034448feSmcpowers
709034448feSmcpowers n++;
710034448feSmcpowers priTemplate[n].type = CKA_EXPONENT_1;
711034448feSmcpowers priTemplate[n].pValue = (caddr_t)exponent_1;
712034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes/2;
713034448feSmcpowers pri_out_attr_count++;
714034448feSmcpowers
715034448feSmcpowers n++;
716034448feSmcpowers priTemplate[n].type = CKA_EXPONENT_2;
717034448feSmcpowers priTemplate[n].pValue = (caddr_t)exponent_2;
718034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes/2;
719034448feSmcpowers pri_out_attr_count++;
720034448feSmcpowers
721034448feSmcpowers n++;
722034448feSmcpowers priTemplate[n].type = CKA_COEFFICIENT;
723034448feSmcpowers priTemplate[n].pValue = (caddr_t)coefficient;
724034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes/2;
725034448feSmcpowers pri_out_attr_count++;
726034448feSmcpowers
727034448feSmcpowers rv = process_object_attributes(priTemplate,
728034448feSmcpowers pri_attr_count - pri_out_attr_count,
729034448feSmcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2);
730034448feSmcpowers if (rv != CKR_OK) {
731034448feSmcpowers goto failed_exit;
732034448feSmcpowers }
733034448feSmcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count;
734034448feSmcpowers
735034448feSmcpowers rv = process_object_attributes(
736034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
737034448feSmcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes,
738034448feSmcpowers &is_token_obj2);
739034448feSmcpowers if (rv != CKR_OK) {
740034448feSmcpowers goto failed_exit;
741034448feSmcpowers }
742034448feSmcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count;
743034448feSmcpowers
744034448feSmcpowers /*
745034448feSmcpowers * The public key and the private key need to contain the same
746034448feSmcpowers * attribute values for CKA_TOKEN.
747034448feSmcpowers */
748034448feSmcpowers if (is_token_obj1 != is_token_obj2) {
749034448feSmcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID;
750034448feSmcpowers goto failed_exit;
751034448feSmcpowers }
752034448feSmcpowers
753034448feSmcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
754034448feSmcpowers obj_nkp.nkp_session = session_p-> k_session;
755034448feSmcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type;
756034448feSmcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter;
757034448feSmcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen;
758034448feSmcpowers
759034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR,
760034448feSmcpowers &obj_nkp)) < 0) {
761034448feSmcpowers if (errno != EINTR)
762034448feSmcpowers break;
763034448feSmcpowers }
764034448feSmcpowers if (r < 0) {
765034448feSmcpowers rv = CKR_FUNCTION_FAILED;
766034448feSmcpowers } else {
767034448feSmcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value);
768034448feSmcpowers }
769034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
770034448feSmcpowers &obj_nkp.nkp_in_public_count);
771034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
772034448feSmcpowers &obj_nkp.nkp_in_private_count);
773034448feSmcpowers
774034448feSmcpowers if (rv != CKR_OK) {
775034448feSmcpowers goto failed_exit;
776034448feSmcpowers }
777034448feSmcpowers
778034448feSmcpowers rv = get_object_attributes(
779034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
780034448feSmcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes);
781034448feSmcpowers if (rv == CRYPTO_SUCCESS) {
782034448feSmcpowers rv = get_object_attributes(
783034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
784034448feSmcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes);
785034448feSmcpowers }
786034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
787034448feSmcpowers &obj_nkp.nkp_out_public_count);
788034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
789034448feSmcpowers &obj_nkp.nkp_out_private_count);
790034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
791034448feSmcpowers goto failed_exit;
792034448feSmcpowers }
793034448feSmcpowers
794034448feSmcpowers /* store generated modulus and public exponent */
795034448feSmcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp,
796034448feSmcpowers session_p, KERNEL_GEN_KEY);
797034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
798034448feSmcpowers goto failed_exit;
799034448feSmcpowers }
800034448feSmcpowers
801034448feSmcpowers /*
802034448feSmcpowers * Copy CKA_PUBLIC_EXPONENT from the public template
803034448feSmcpowers * to the private template.
804034448feSmcpowers */
805034448feSmcpowers rv = copy_attribute(CKA_PUBLIC_EXPONENT, pubTemplate,
806034448feSmcpowers pub_attr_count, &priTemplate[pri_attr_count]);
807034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
808034448feSmcpowers goto failed_exit;
809034448feSmcpowers }
810034448feSmcpowers
811034448feSmcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 1, new_pri_objp,
812034448feSmcpowers session_p, KERNEL_GEN_KEY);
813034448feSmcpowers (void) free(priTemplate[pri_attr_count].pValue);
814034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
815034448feSmcpowers goto failed_exit;
816034448feSmcpowers }
817034448feSmcpowers (void) free(pubTemplate);
818034448feSmcpowers (void) free(priTemplate);
819034448feSmcpowers
820034448feSmcpowers new_pub_objp->is_lib_obj = B_TRUE;
821034448feSmcpowers new_pri_objp->is_lib_obj = B_TRUE;
822034448feSmcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
823034448feSmcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
824034448feSmcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
825034448feSmcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
826034448feSmcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
827034448feSmcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
828034448feSmcpowers return (CKR_OK);
829034448feSmcpowers
830034448feSmcpowers failed_exit:
831034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
832034448feSmcpowers &obj_nkp.nkp_in_public_count);
833034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
834034448feSmcpowers &obj_nkp.nkp_out_public_count);
835034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
836034448feSmcpowers &obj_nkp.nkp_in_private_count);
837034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
838034448feSmcpowers &obj_nkp.nkp_out_private_count);
839034448feSmcpowers if (pubTemplate != NULL) {
840034448feSmcpowers (void) free(pubTemplate);
841034448feSmcpowers }
842034448feSmcpowers if (priTemplate != NULL) {
843034448feSmcpowers (void) free(priTemplate);
844034448feSmcpowers }
845034448feSmcpowers return (rv);
846034448feSmcpowers }
847034448feSmcpowers
848034448feSmcpowers CK_RV
key_gen_dh_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_pub_objp,kernel_object_t * new_pri_objp)849034448feSmcpowers key_gen_dh_by_value(CK_MECHANISM_PTR pMechanism,
850034448feSmcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
851034448feSmcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
852034448feSmcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type,
853034448feSmcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp)
854034448feSmcpowers {
855034448feSmcpowers crypto_nostore_generate_key_pair_t obj_nkp;
856034448feSmcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL;
857034448feSmcpowers CK_ATTRIBUTE_PTR priTemplate = NULL;
858034448feSmcpowers CK_RV rv = CKR_OK;
859034448feSmcpowers CK_BBOOL is_token_obj1 = FALSE;
860034448feSmcpowers CK_BBOOL is_token_obj2 = FALSE;
861034448feSmcpowers uint_t pub_attr_count, pri_attr_count;
862034448feSmcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0;
863034448feSmcpowers char public_value[256];
864034448feSmcpowers char private_value[256];
865034448feSmcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY;
866034448feSmcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY;
867034448feSmcpowers CK_ULONG key_type;
868034448feSmcpowers boolean_t has_class, has_key_type;
869034448feSmcpowers int n, r;
870034448feSmcpowers
871034448feSmcpowers obj_nkp.nkp_in_public_count = 0;
872034448feSmcpowers obj_nkp.nkp_out_public_count = 0;
873034448feSmcpowers obj_nkp.nkp_in_private_count = 0;
874034448feSmcpowers obj_nkp.nkp_out_private_count = 0;
875034448feSmcpowers
876034448feSmcpowers /*
877034448feSmcpowers * Add CKA_VALUE to the public template.
878034448feSmcpowers * This attribute must not be in the template.
879034448feSmcpowers */
880034448feSmcpowers if (attribute_in_template(CKA_VALUE, pPublicKeyTemplate,
881034448feSmcpowers ulPublicKeyAttributeCount)) {
882034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT;
883034448feSmcpowers goto failed_exit;
884034448feSmcpowers }
885034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate,
886034448feSmcpowers ulPublicKeyAttributeCount);
887034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate,
888034448feSmcpowers ulPublicKeyAttributeCount);
889034448feSmcpowers
890034448feSmcpowers pub_attr_count = ulPublicKeyAttributeCount + 1;
891034448feSmcpowers if (!has_class)
892034448feSmcpowers pub_attr_count++;
893034448feSmcpowers if (!has_key_type)
894034448feSmcpowers pub_attr_count++;
895034448feSmcpowers pubTemplate = grow_template(pPublicKeyTemplate,
896034448feSmcpowers ulPublicKeyAttributeCount, pub_attr_count);
897034448feSmcpowers if (pubTemplate == NULL) {
898034448feSmcpowers rv = CKR_HOST_MEMORY;
899034448feSmcpowers goto failed_exit;
900034448feSmcpowers }
901034448feSmcpowers
902034448feSmcpowers n = ulPublicKeyAttributeCount;
903034448feSmcpowers if (!has_class) {
904034448feSmcpowers pubTemplate[n].type = CKA_CLASS;
905034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&pub_class;
906034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (pub_class);
907034448feSmcpowers n++;
908034448feSmcpowers }
909034448feSmcpowers if (!has_key_type) {
910034448feSmcpowers pubTemplate[n].type = CKA_KEY_TYPE;
911034448feSmcpowers key_type = CKK_DH;
912034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&key_type;
913034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (key_type);
914034448feSmcpowers n++;
915034448feSmcpowers }
916034448feSmcpowers pubTemplate[n].type = CKA_VALUE;
917034448feSmcpowers pubTemplate[n].pValue = (caddr_t)public_value;
918034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (public_value);
919034448feSmcpowers pub_out_attr_count++;
920034448feSmcpowers
921034448feSmcpowers rv = process_object_attributes(pubTemplate,
922034448feSmcpowers pub_attr_count - pub_out_attr_count,
923034448feSmcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1);
924034448feSmcpowers if (rv != CKR_OK) {
925034448feSmcpowers goto failed_exit;
926034448feSmcpowers }
927034448feSmcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count;
928034448feSmcpowers
929034448feSmcpowers rv = process_object_attributes(
930034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
931034448feSmcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes,
932034448feSmcpowers &is_token_obj1);
933034448feSmcpowers if (rv != CKR_OK) {
934034448feSmcpowers goto failed_exit;
935034448feSmcpowers }
936034448feSmcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count;
937034448feSmcpowers
938034448feSmcpowers /*
939034448feSmcpowers * Cannot create a token object with a READ-ONLY
940034448feSmcpowers * session.
941034448feSmcpowers */
942034448feSmcpowers if (is_token_obj1 && session_p->ses_RO) {
943034448feSmcpowers rv = CKR_SESSION_READ_ONLY;
944034448feSmcpowers goto failed_exit;
945034448feSmcpowers }
946034448feSmcpowers
947034448feSmcpowers /*
948034448feSmcpowers * CKA_BASE, CKA_PRIME, and CKA_VALUE must not appear
949034448feSmcpowers * in private template.
950034448feSmcpowers */
951034448feSmcpowers if (attribute_in_template(CKA_BASE, pPrivateKeyTemplate,
952034448feSmcpowers ulPrivateKeyAttributeCount) ||
953034448feSmcpowers attribute_in_template(CKA_PRIME, pPrivateKeyTemplate,
954034448feSmcpowers ulPrivateKeyAttributeCount) ||
955034448feSmcpowers attribute_in_template(CKA_VALUE, pPrivateKeyTemplate,
956034448feSmcpowers ulPrivateKeyAttributeCount)) {
957034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT;
958034448feSmcpowers goto failed_exit;
959034448feSmcpowers }
960034448feSmcpowers
961034448feSmcpowers if (attribute_in_template(CKA_VALUE, pPrivateKeyTemplate,
962034448feSmcpowers ulPrivateKeyAttributeCount)) {
963034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT;
964034448feSmcpowers goto failed_exit;
965034448feSmcpowers }
966034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate,
967034448feSmcpowers ulPrivateKeyAttributeCount);
968034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate,
969034448feSmcpowers ulPrivateKeyAttributeCount);
970034448feSmcpowers
971034448feSmcpowers pri_attr_count = ulPrivateKeyAttributeCount + 1;
972034448feSmcpowers if (!has_class)
973034448feSmcpowers pri_attr_count++;
974034448feSmcpowers if (!has_key_type)
975034448feSmcpowers pri_attr_count++;
976034448feSmcpowers
977034448feSmcpowers /* allocate space for CKA_BASE and CKA_PRIME */
978034448feSmcpowers priTemplate = grow_template(pPrivateKeyTemplate,
979034448feSmcpowers ulPrivateKeyAttributeCount, pri_attr_count + 2);
980034448feSmcpowers if (priTemplate == NULL) {
981034448feSmcpowers rv = CKR_HOST_MEMORY;
982034448feSmcpowers goto failed_exit;
983034448feSmcpowers }
984034448feSmcpowers n = ulPrivateKeyAttributeCount;
985034448feSmcpowers if (!has_class) {
986034448feSmcpowers priTemplate[n].type = CKA_CLASS;
987034448feSmcpowers priTemplate[n].pValue = (caddr_t)&pri_class;
988034448feSmcpowers priTemplate[n].ulValueLen = sizeof (pri_class);
989034448feSmcpowers n++;
990034448feSmcpowers }
991034448feSmcpowers if (!has_key_type) {
992034448feSmcpowers priTemplate[n].type = CKA_KEY_TYPE;
993034448feSmcpowers key_type = CKK_DH;
994034448feSmcpowers priTemplate[n].pValue = (caddr_t)&key_type;
995034448feSmcpowers priTemplate[n].ulValueLen = sizeof (key_type);
996034448feSmcpowers n++;
997034448feSmcpowers }
998034448feSmcpowers priTemplate[n].type = CKA_VALUE;
999034448feSmcpowers priTemplate[n].pValue = (caddr_t)private_value;
1000034448feSmcpowers priTemplate[n].ulValueLen = sizeof (private_value);
1001034448feSmcpowers pri_out_attr_count++;
1002034448feSmcpowers
1003034448feSmcpowers rv = process_object_attributes(priTemplate,
1004034448feSmcpowers pri_attr_count - pri_out_attr_count,
1005034448feSmcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2);
1006034448feSmcpowers if (rv != CKR_OK) {
1007034448feSmcpowers goto failed_exit;
1008034448feSmcpowers }
1009034448feSmcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count;
1010034448feSmcpowers
1011034448feSmcpowers rv = process_object_attributes(
1012034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
1013034448feSmcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes,
1014034448feSmcpowers &is_token_obj2);
1015034448feSmcpowers if (rv != CKR_OK) {
1016034448feSmcpowers goto failed_exit;
1017034448feSmcpowers }
1018034448feSmcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count;
1019034448feSmcpowers
1020034448feSmcpowers /*
1021034448feSmcpowers * The public key and the private key need to contain the same
1022034448feSmcpowers * attribute values for CKA_TOKEN.
1023034448feSmcpowers */
1024034448feSmcpowers if (is_token_obj1 != is_token_obj2) {
1025034448feSmcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID;
1026034448feSmcpowers goto failed_exit;
1027034448feSmcpowers }
1028034448feSmcpowers
1029034448feSmcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
1030034448feSmcpowers obj_nkp.nkp_session = session_p-> k_session;
1031034448feSmcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type;
1032034448feSmcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter;
1033034448feSmcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen;
1034034448feSmcpowers
1035034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR,
1036034448feSmcpowers &obj_nkp)) < 0) {
1037034448feSmcpowers if (errno != EINTR)
1038034448feSmcpowers break;
1039034448feSmcpowers }
1040034448feSmcpowers if (r < 0) {
1041034448feSmcpowers rv = CKR_FUNCTION_FAILED;
1042034448feSmcpowers } else {
1043034448feSmcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value);
1044034448feSmcpowers }
1045034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
1046034448feSmcpowers &obj_nkp.nkp_in_public_count);
1047034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
1048034448feSmcpowers &obj_nkp.nkp_in_private_count);
1049034448feSmcpowers
1050034448feSmcpowers if (rv != CKR_OK) {
1051034448feSmcpowers goto failed_exit;
1052034448feSmcpowers }
1053034448feSmcpowers
1054034448feSmcpowers rv = get_object_attributes(
1055034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
1056034448feSmcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes);
1057034448feSmcpowers if (rv == CRYPTO_SUCCESS) {
1058034448feSmcpowers rv = get_object_attributes(
1059034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
1060034448feSmcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes);
1061034448feSmcpowers }
1062034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
1063034448feSmcpowers &obj_nkp.nkp_out_public_count);
1064034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
1065034448feSmcpowers &obj_nkp.nkp_out_private_count);
1066034448feSmcpowers
1067034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
1068034448feSmcpowers goto failed_exit;
1069034448feSmcpowers }
1070034448feSmcpowers
1071034448feSmcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp,
1072034448feSmcpowers session_p, KERNEL_GEN_KEY);
1073034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
1074034448feSmcpowers goto failed_exit;
1075034448feSmcpowers }
1076034448feSmcpowers
1077034448feSmcpowers /*
1078034448feSmcpowers * Copy CKA_BASE and CKA_PRIME from the public template
1079034448feSmcpowers * to the private template.
1080034448feSmcpowers */
1081034448feSmcpowers rv = copy_attribute(CKA_BASE, pubTemplate, pub_attr_count,
1082034448feSmcpowers &priTemplate[pri_attr_count]);
1083034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
1084034448feSmcpowers goto failed_exit;
1085034448feSmcpowers }
1086034448feSmcpowers rv = copy_attribute(CKA_PRIME, pubTemplate, pub_attr_count,
1087034448feSmcpowers &priTemplate[pri_attr_count + 1]);
1088034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
1089034448feSmcpowers (void) free(priTemplate[pri_attr_count].pValue);
1090034448feSmcpowers goto failed_exit;
1091034448feSmcpowers }
1092034448feSmcpowers
1093034448feSmcpowers /* +2 to account for CKA_BASE and CKA_PRIME */
1094034448feSmcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 2,
1095034448feSmcpowers new_pri_objp, session_p, KERNEL_GEN_KEY);
1096034448feSmcpowers (void) free(priTemplate[pri_attr_count].pValue);
1097034448feSmcpowers (void) free(priTemplate[pri_attr_count + 1].pValue);
1098034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
1099034448feSmcpowers goto failed_exit;
1100034448feSmcpowers }
1101034448feSmcpowers (void) free(pubTemplate);
1102034448feSmcpowers (void) free(priTemplate);
1103034448feSmcpowers
1104034448feSmcpowers new_pub_objp->is_lib_obj = B_TRUE;
1105034448feSmcpowers new_pri_objp->is_lib_obj = B_TRUE;
1106034448feSmcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
1107034448feSmcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
1108034448feSmcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
1109034448feSmcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1110034448feSmcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
1111034448feSmcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1112034448feSmcpowers return (CKR_OK);
1113034448feSmcpowers
1114034448feSmcpowers failed_exit:
1115034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
1116034448feSmcpowers &obj_nkp.nkp_in_public_count);
1117034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
1118034448feSmcpowers &obj_nkp.nkp_out_public_count);
1119034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
1120034448feSmcpowers &obj_nkp.nkp_in_private_count);
1121034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
1122034448feSmcpowers &obj_nkp.nkp_out_private_count);
1123034448feSmcpowers if (pubTemplate != NULL) {
1124034448feSmcpowers (void) free(pubTemplate);
1125034448feSmcpowers }
1126034448feSmcpowers if (priTemplate != NULL) {
1127034448feSmcpowers (void) free(priTemplate);
1128034448feSmcpowers }
1129034448feSmcpowers return (rv);
1130034448feSmcpowers }
1131034448feSmcpowers
1132034448feSmcpowers CK_RV
key_gen_ec_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_pub_objp,kernel_object_t * new_pri_objp)1133034448feSmcpowers key_gen_ec_by_value(CK_MECHANISM_PTR pMechanism,
1134034448feSmcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
1135034448feSmcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
1136034448feSmcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type,
1137034448feSmcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp)
1138034448feSmcpowers {
1139034448feSmcpowers crypto_nostore_generate_key_pair_t obj_nkp;
1140034448feSmcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL;
1141034448feSmcpowers CK_ATTRIBUTE_PTR priTemplate = NULL;
1142034448feSmcpowers CK_RV rv = CKR_OK;
1143034448feSmcpowers CK_BBOOL is_token_obj1 = FALSE;
1144034448feSmcpowers CK_BBOOL is_token_obj2 = FALSE;
1145034448feSmcpowers uint_t pub_attr_count, pri_attr_count;
1146034448feSmcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0;
1147f9fbec18Smcpowers char value[EC_MAX_VALUE_LEN];
1148f9fbec18Smcpowers char point[EC_MAX_POINT_LEN];
1149034448feSmcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY;
1150034448feSmcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY;
1151034448feSmcpowers CK_ULONG key_type;
1152034448feSmcpowers boolean_t has_class, has_key_type;
1153034448feSmcpowers int n, r;
1154034448feSmcpowers
1155034448feSmcpowers obj_nkp.nkp_in_public_count = 0;
1156034448feSmcpowers obj_nkp.nkp_out_public_count = 0;
1157034448feSmcpowers obj_nkp.nkp_in_private_count = 0;
1158034448feSmcpowers obj_nkp.nkp_out_private_count = 0;
1159034448feSmcpowers
1160034448feSmcpowers /*
1161034448feSmcpowers * Add CKA_EC_POINT to the public template.
1162034448feSmcpowers * This is the generated value Q. This attribute
1163034448feSmcpowers * must not be in the template.
1164034448feSmcpowers */
1165034448feSmcpowers if (attribute_in_template(CKA_EC_POINT, pPublicKeyTemplate,
1166034448feSmcpowers ulPublicKeyAttributeCount)) {
1167034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT;
1168034448feSmcpowers goto failed_exit;
1169034448feSmcpowers }
1170034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate,
1171034448feSmcpowers ulPublicKeyAttributeCount);
1172034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate,
1173034448feSmcpowers ulPublicKeyAttributeCount);
1174034448feSmcpowers
1175034448feSmcpowers pub_attr_count = ulPublicKeyAttributeCount + 1;
1176034448feSmcpowers if (!has_class)
1177034448feSmcpowers pub_attr_count++;
1178034448feSmcpowers if (!has_key_type)
1179034448feSmcpowers pub_attr_count++;
1180034448feSmcpowers pubTemplate = grow_template(pPublicKeyTemplate,
1181034448feSmcpowers ulPublicKeyAttributeCount, pub_attr_count);
1182034448feSmcpowers if (pubTemplate == NULL) {
1183034448feSmcpowers rv = CKR_HOST_MEMORY;
1184034448feSmcpowers goto failed_exit;
1185034448feSmcpowers }
1186034448feSmcpowers
1187034448feSmcpowers n = ulPublicKeyAttributeCount;
1188034448feSmcpowers if (!has_class) {
1189034448feSmcpowers pubTemplate[n].type = CKA_CLASS;
1190034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&pub_class;
1191034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (pub_class);
1192034448feSmcpowers n++;
1193034448feSmcpowers }
1194034448feSmcpowers if (!has_key_type) {
1195034448feSmcpowers pubTemplate[n].type = CKA_KEY_TYPE;
1196034448feSmcpowers key_type = CKK_EC;
1197034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&key_type;
1198034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (key_type);
1199034448feSmcpowers n++;
1200034448feSmcpowers }
1201034448feSmcpowers pubTemplate[n].type = CKA_EC_POINT;
1202034448feSmcpowers pubTemplate[n].pValue = (caddr_t)point;
1203034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (point);
1204034448feSmcpowers pub_out_attr_count++;
1205034448feSmcpowers
1206034448feSmcpowers rv = process_object_attributes(pubTemplate,
1207034448feSmcpowers pub_attr_count - pub_out_attr_count,
1208034448feSmcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1);
1209034448feSmcpowers if (rv != CKR_OK) {
1210034448feSmcpowers goto failed_exit;
1211034448feSmcpowers }
1212034448feSmcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count;
1213034448feSmcpowers
1214034448feSmcpowers rv = process_object_attributes(
1215034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
1216034448feSmcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes,
1217034448feSmcpowers &is_token_obj1);
1218034448feSmcpowers if (rv != CKR_OK) {
1219034448feSmcpowers goto failed_exit;
1220034448feSmcpowers }
1221034448feSmcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count;
1222034448feSmcpowers
1223034448feSmcpowers /*
1224034448feSmcpowers * Cannot create a token object with a READ-ONLY
1225034448feSmcpowers * session.
1226034448feSmcpowers */
1227034448feSmcpowers if (is_token_obj1 && session_p->ses_RO) {
1228034448feSmcpowers rv = CKR_SESSION_READ_ONLY;
1229034448feSmcpowers goto failed_exit;
1230034448feSmcpowers }
1231034448feSmcpowers
1232034448feSmcpowers /*
1233034448feSmcpowers * CKA_EC_PARAMS and CKA_VALUE must not appear in
1234034448feSmcpowers * private template.
1235034448feSmcpowers */
1236034448feSmcpowers if (attribute_in_template(CKA_EC_PARAMS, pPrivateKeyTemplate,
1237034448feSmcpowers ulPrivateKeyAttributeCount) ||
1238034448feSmcpowers attribute_in_template(CKA_VALUE, pPrivateKeyTemplate,
1239034448feSmcpowers ulPrivateKeyAttributeCount)) {
1240034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT;
1241034448feSmcpowers goto failed_exit;
1242034448feSmcpowers }
1243034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate,
1244034448feSmcpowers ulPrivateKeyAttributeCount);
1245034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate,
1246034448feSmcpowers ulPrivateKeyAttributeCount);
1247034448feSmcpowers
1248034448feSmcpowers pri_attr_count = ulPrivateKeyAttributeCount + 1;
1249034448feSmcpowers if (!has_class)
1250034448feSmcpowers pri_attr_count++;
1251034448feSmcpowers if (!has_key_type)
1252034448feSmcpowers pri_attr_count++;
1253034448feSmcpowers
1254034448feSmcpowers /* allocate space for CKA_EC_PARAMS */
1255034448feSmcpowers priTemplate = grow_template(pPrivateKeyTemplate,
1256034448feSmcpowers ulPrivateKeyAttributeCount, pri_attr_count + 1);
1257034448feSmcpowers if (priTemplate == NULL) {
1258034448feSmcpowers rv = CKR_HOST_MEMORY;
1259034448feSmcpowers goto failed_exit;
1260034448feSmcpowers }
1261034448feSmcpowers n = ulPrivateKeyAttributeCount;
1262034448feSmcpowers if (!has_class) {
1263034448feSmcpowers priTemplate[n].type = CKA_CLASS;
1264034448feSmcpowers priTemplate[n].pValue = (caddr_t)&pri_class;
1265034448feSmcpowers priTemplate[n].ulValueLen = sizeof (pri_class);
1266034448feSmcpowers n++;
1267034448feSmcpowers }
1268034448feSmcpowers if (!has_key_type) {
1269034448feSmcpowers priTemplate[n].type = CKA_KEY_TYPE;
1270034448feSmcpowers key_type = CKK_EC;
1271034448feSmcpowers priTemplate[n].pValue = (caddr_t)&key_type;
1272034448feSmcpowers priTemplate[n].ulValueLen = sizeof (key_type);
1273034448feSmcpowers n++;
1274034448feSmcpowers }
1275034448feSmcpowers priTemplate[n].type = CKA_VALUE;
1276034448feSmcpowers priTemplate[n].pValue = (caddr_t)value;
1277034448feSmcpowers priTemplate[n].ulValueLen = sizeof (value);
1278034448feSmcpowers pri_out_attr_count++;
1279034448feSmcpowers
1280034448feSmcpowers rv = process_object_attributes(priTemplate,
1281034448feSmcpowers pri_attr_count - pri_out_attr_count,
1282034448feSmcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2);
1283034448feSmcpowers if (rv != CKR_OK) {
1284034448feSmcpowers goto failed_exit;
1285034448feSmcpowers }
1286034448feSmcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count;
1287034448feSmcpowers
1288034448feSmcpowers rv = process_object_attributes(
1289034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
1290034448feSmcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes,
1291034448feSmcpowers &is_token_obj2);
1292034448feSmcpowers if (rv != CKR_OK) {
1293034448feSmcpowers goto failed_exit;
1294034448feSmcpowers }
1295034448feSmcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count;
1296034448feSmcpowers
1297034448feSmcpowers /*
1298034448feSmcpowers * The public key and the private key need to contain the same
1299034448feSmcpowers * attribute values for CKA_TOKEN.
1300034448feSmcpowers */
1301034448feSmcpowers if (is_token_obj1 != is_token_obj2) {
1302034448feSmcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID;
1303034448feSmcpowers goto failed_exit;
1304034448feSmcpowers }
1305034448feSmcpowers
1306034448feSmcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
1307034448feSmcpowers obj_nkp.nkp_session = session_p-> k_session;
1308034448feSmcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type;
1309034448feSmcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter;
1310034448feSmcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen;
1311034448feSmcpowers
1312034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR,
1313034448feSmcpowers &obj_nkp)) < 0) {
1314034448feSmcpowers if (errno != EINTR)
1315034448feSmcpowers break;
1316034448feSmcpowers }
1317034448feSmcpowers if (r < 0) {
1318034448feSmcpowers rv = CKR_FUNCTION_FAILED;
1319034448feSmcpowers } else {
1320034448feSmcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value);
1321034448feSmcpowers }
1322034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
1323034448feSmcpowers &obj_nkp.nkp_in_public_count);
1324034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
1325034448feSmcpowers &obj_nkp.nkp_in_private_count);
1326034448feSmcpowers
1327034448feSmcpowers if (rv != CKR_OK) {
1328034448feSmcpowers goto failed_exit;
1329034448feSmcpowers }
1330034448feSmcpowers
1331034448feSmcpowers rv = get_object_attributes(
1332034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
1333034448feSmcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes);
1334034448feSmcpowers if (rv == CRYPTO_SUCCESS) {
1335034448feSmcpowers rv = get_object_attributes(
1336034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
1337034448feSmcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes);
1338034448feSmcpowers }
1339034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
1340034448feSmcpowers &obj_nkp.nkp_out_public_count);
1341034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
1342034448feSmcpowers &obj_nkp.nkp_out_private_count);
1343034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
1344034448feSmcpowers goto failed_exit;
1345034448feSmcpowers }
1346034448feSmcpowers
1347034448feSmcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp,
1348034448feSmcpowers session_p, KERNEL_GEN_KEY);
1349034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
1350034448feSmcpowers goto failed_exit;
1351034448feSmcpowers }
1352034448feSmcpowers
1353034448feSmcpowers /*
1354034448feSmcpowers * Copy CKA_EC_PARAMS from the public template to the
1355034448feSmcpowers * private template.
1356034448feSmcpowers */
1357034448feSmcpowers rv = copy_attribute(CKA_EC_PARAMS, pubTemplate, pub_attr_count,
1358034448feSmcpowers &priTemplate[pri_attr_count]);
1359034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
1360034448feSmcpowers goto failed_exit;
1361034448feSmcpowers }
1362034448feSmcpowers
1363034448feSmcpowers /* +1 to account for CKA_EC_PARAMS */
1364034448feSmcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 1,
1365034448feSmcpowers new_pri_objp, session_p, KERNEL_GEN_KEY);
1366034448feSmcpowers (void) free(priTemplate[pri_attr_count].pValue);
1367034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
1368034448feSmcpowers goto failed_exit;
1369034448feSmcpowers }
1370034448feSmcpowers (void) free(pubTemplate);
1371034448feSmcpowers (void) free(priTemplate);
1372034448feSmcpowers
1373034448feSmcpowers new_pub_objp->is_lib_obj = B_TRUE;
1374034448feSmcpowers new_pri_objp->is_lib_obj = B_TRUE;
1375034448feSmcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
1376034448feSmcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
1377034448feSmcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
1378034448feSmcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1379034448feSmcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
1380034448feSmcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1381034448feSmcpowers return (CKR_OK);
1382034448feSmcpowers
1383034448feSmcpowers failed_exit:
1384034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
1385034448feSmcpowers &obj_nkp.nkp_in_public_count);
1386034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
1387034448feSmcpowers &obj_nkp.nkp_out_public_count);
1388034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
1389034448feSmcpowers &obj_nkp.nkp_in_private_count);
1390034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
1391034448feSmcpowers &obj_nkp.nkp_out_private_count);
1392034448feSmcpowers if (pubTemplate != NULL) {
1393034448feSmcpowers (void) free(pubTemplate);
1394034448feSmcpowers }
1395034448feSmcpowers if (priTemplate != NULL) {
1396034448feSmcpowers (void) free(priTemplate);
1397034448feSmcpowers }
1398034448feSmcpowers return (rv);
1399034448feSmcpowers }
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate CK_RV
C_GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey)14027c478bd9Sstevel@tonic-gate C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
14037c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
14047c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
14057c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
14067c478bd9Sstevel@tonic-gate {
14077c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
14087c478bd9Sstevel@tonic-gate kernel_session_t *session_p;
14097c478bd9Sstevel@tonic-gate kernel_object_t *new_pub_objp = NULL;
14107c478bd9Sstevel@tonic-gate kernel_object_t *new_pri_objp = NULL;
14117c478bd9Sstevel@tonic-gate kernel_slot_t *pslot;
14127c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE;
14137c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj1;
14147c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj2;
14157c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj1 = FALSE;
14167c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj2 = FALSE;
14177c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type;
14187c478bd9Sstevel@tonic-gate int r;
1419034448feSmcpowers CK_RV (*func)(CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG,
1420034448feSmcpowers CK_ATTRIBUTE_PTR, CK_ULONG, kernel_session_t *, crypto_mech_type_t,
1421034448feSmcpowers kernel_object_t *, kernel_object_t *);
14227c478bd9Sstevel@tonic-gate
14237c478bd9Sstevel@tonic-gate if (!kernel_initialized)
14247c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
14257c478bd9Sstevel@tonic-gate
14267c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */
14277c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
14287c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
14297c478bd9Sstevel@tonic-gate return (rv);
14307c478bd9Sstevel@tonic-gate
14317c478bd9Sstevel@tonic-gate if ((pMechanism == NULL) || (phPublicKey == NULL) ||
14327c478bd9Sstevel@tonic-gate (phPrivateKey == NULL)) {
14337c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
14347c478bd9Sstevel@tonic-gate goto failed_exit;
14357c478bd9Sstevel@tonic-gate }
14367c478bd9Sstevel@tonic-gate
14377c478bd9Sstevel@tonic-gate if ((pPublicKeyTemplate == NULL) && (ulPublicKeyAttributeCount != 0)) {
14387c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
14397c478bd9Sstevel@tonic-gate goto failed_exit;
14407c478bd9Sstevel@tonic-gate }
14417c478bd9Sstevel@tonic-gate
14427c478bd9Sstevel@tonic-gate if ((pPrivateKeyTemplate == NULL) &&
14437c478bd9Sstevel@tonic-gate (ulPrivateKeyAttributeCount != 0)) {
14447c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
14457c478bd9Sstevel@tonic-gate goto failed_exit;
14467c478bd9Sstevel@tonic-gate }
14477c478bd9Sstevel@tonic-gate
14487c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */
14497c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
14507c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
14517c478bd9Sstevel@tonic-gate goto failed_exit;
14527c478bd9Sstevel@tonic-gate }
14537c478bd9Sstevel@tonic-gate
14547c478bd9Sstevel@tonic-gate /* Create an object wrapper for the public key */
14557c478bd9Sstevel@tonic-gate new_pub_objp = calloc(1, sizeof (kernel_object_t));
14567c478bd9Sstevel@tonic-gate if (new_pub_objp == NULL) {
14577c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
14587c478bd9Sstevel@tonic-gate goto failed_exit;
14597c478bd9Sstevel@tonic-gate }
14607c478bd9Sstevel@tonic-gate
14617c478bd9Sstevel@tonic-gate /* Create an object wrapper for the private key. */
14627c478bd9Sstevel@tonic-gate new_pri_objp = calloc(1, sizeof (kernel_object_t));
14637c478bd9Sstevel@tonic-gate if (new_pri_objp == NULL) {
14647c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
14657c478bd9Sstevel@tonic-gate goto failed_exit;
14667c478bd9Sstevel@tonic-gate }
14677c478bd9Sstevel@tonic-gate
1468034448feSmcpowers /*
1469034448feSmcpowers * Special Case: if token does not support object creation,
1470034448feSmcpowers * but does support key generation by value, then create a session
1471034448feSmcpowers * object and initialize with values returned by token.
1472034448feSmcpowers */
1473034448feSmcpowers pslot = slot_table[session_p->ses_slotid];
1474034448feSmcpowers if (!pslot->sl_func_list.fl_object_create) {
1475034448feSmcpowers switch (pMechanism->mechanism) {
1476034448feSmcpowers case CKM_RSA_PKCS_KEY_PAIR_GEN:
1477034448feSmcpowers func = key_gen_rsa_by_value;
1478034448feSmcpowers break;
1479034448feSmcpowers
1480034448feSmcpowers case CKM_DH_PKCS_KEY_PAIR_GEN:
1481034448feSmcpowers func = key_gen_dh_by_value;
1482034448feSmcpowers break;
1483034448feSmcpowers
1484034448feSmcpowers case CKM_EC_KEY_PAIR_GEN:
1485034448feSmcpowers func = key_gen_ec_by_value;
1486034448feSmcpowers break;
1487034448feSmcpowers
1488034448feSmcpowers default:
1489034448feSmcpowers rv = CKR_MECHANISM_INVALID;
1490034448feSmcpowers goto failed_exit;
1491034448feSmcpowers }
1492034448feSmcpowers rv = (*func)(pMechanism, pPublicKeyTemplate,
1493034448feSmcpowers ulPublicKeyAttributeCount, pPrivateKeyTemplate,
1494034448feSmcpowers ulPrivateKeyAttributeCount, session_p, k_mech_type,
1495034448feSmcpowers new_pub_objp, new_pri_objp);
1496034448feSmcpowers if (rv != CKR_OK)
1497034448feSmcpowers goto failed_exit;
1498034448feSmcpowers } else {
1499034448feSmcpowers crypto_object_generate_key_pair_t obj_kp;
1500034448feSmcpowers
15017c478bd9Sstevel@tonic-gate /* Process the public key attributes. */
15027c478bd9Sstevel@tonic-gate rv = process_object_attributes(pPublicKeyTemplate,
15037c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount, &obj_kp.kp_public_attributes,
15047c478bd9Sstevel@tonic-gate &is_token_obj1);
15057c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
15067c478bd9Sstevel@tonic-gate goto failed_exit;
15077c478bd9Sstevel@tonic-gate }
15087c478bd9Sstevel@tonic-gate
15097c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */
15107c478bd9Sstevel@tonic-gate if (is_token_obj1 && session_p->ses_RO) {
15117c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes,
15127c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount);
15137c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY;
15147c478bd9Sstevel@tonic-gate goto failed_exit;
15157c478bd9Sstevel@tonic-gate }
15167c478bd9Sstevel@tonic-gate
15177c478bd9Sstevel@tonic-gate /* Process the private key attributes. */
15187c478bd9Sstevel@tonic-gate rv = process_object_attributes(pPrivateKeyTemplate,
15197c478bd9Sstevel@tonic-gate ulPrivateKeyAttributeCount, &obj_kp.kp_private_attributes,
15207c478bd9Sstevel@tonic-gate &is_token_obj2);
15217c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
15227c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes,
15237c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount);
15247c478bd9Sstevel@tonic-gate goto failed_exit;
15257c478bd9Sstevel@tonic-gate }
15267c478bd9Sstevel@tonic-gate
15277c478bd9Sstevel@tonic-gate /*
15287c478bd9Sstevel@tonic-gate * The public key and the private key need to contain the same
15297c478bd9Sstevel@tonic-gate * attribute values for CKA_TOKEN.
15307c478bd9Sstevel@tonic-gate */
15317c478bd9Sstevel@tonic-gate if (is_token_obj1 != is_token_obj2) {
15327c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes,
15337c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount);
15347c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_private_attributes,
15357c478bd9Sstevel@tonic-gate ulPrivateKeyAttributeCount);
15367c478bd9Sstevel@tonic-gate rv = CKR_ATTRIBUTE_VALUE_INVALID;
15377c478bd9Sstevel@tonic-gate goto failed_exit;
15387c478bd9Sstevel@tonic-gate }
15397c478bd9Sstevel@tonic-gate
15407c478bd9Sstevel@tonic-gate /* Call the CRYPTO_GENERATE_KEY_PAIR ioctl. */
15417c478bd9Sstevel@tonic-gate obj_kp.kp_session = session_p-> k_session;
15427c478bd9Sstevel@tonic-gate obj_kp.kp_mechanism.cm_type = k_mech_type;
15437c478bd9Sstevel@tonic-gate obj_kp.kp_mechanism.cm_param = pMechanism->pParameter;
15447c478bd9Sstevel@tonic-gate obj_kp.kp_mechanism.cm_param_len = pMechanism->ulParameterLen;
15457c478bd9Sstevel@tonic-gate obj_kp.kp_public_count = ulPublicKeyAttributeCount;
15467c478bd9Sstevel@tonic-gate obj_kp.kp_private_count = ulPrivateKeyAttributeCount;
15477c478bd9Sstevel@tonic-gate
1548034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY_PAIR,
1549034448feSmcpowers &obj_kp)) < 0) {
15507c478bd9Sstevel@tonic-gate if (errno != EINTR)
15517c478bd9Sstevel@tonic-gate break;
15527c478bd9Sstevel@tonic-gate }
15537c478bd9Sstevel@tonic-gate if (r < 0) {
15547c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
15557c478bd9Sstevel@tonic-gate } else {
15567c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_kp.kp_return_value);
15577c478bd9Sstevel@tonic-gate }
15587c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes,
15597c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount);
15607c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_private_attributes,
15617c478bd9Sstevel@tonic-gate ulPrivateKeyAttributeCount);
15627c478bd9Sstevel@tonic-gate
1563034448feSmcpowers if (rv != CKR_OK)
15647c478bd9Sstevel@tonic-gate goto failed_exit;
15657c478bd9Sstevel@tonic-gate
15667c478bd9Sstevel@tonic-gate /* Get the CKA_PRIVATE value for the key pair. */
15677c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_kp.kp_public_handle,
15687c478bd9Sstevel@tonic-gate &is_pri_obj1);
15697c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
15707c478bd9Sstevel@tonic-gate goto failed_exit;
15717c478bd9Sstevel@tonic-gate }
15727c478bd9Sstevel@tonic-gate
15737c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_kp.kp_private_handle,
15747c478bd9Sstevel@tonic-gate &is_pri_obj2);
15757c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
15767c478bd9Sstevel@tonic-gate goto failed_exit;
15777c478bd9Sstevel@tonic-gate }
15787c478bd9Sstevel@tonic-gate
15797c478bd9Sstevel@tonic-gate /*
1580034448feSmcpowers * Store the kernel public key handle into the public key
1581034448feSmcpowers * object and finish the public key object initialization.
15827c478bd9Sstevel@tonic-gate */
15837c478bd9Sstevel@tonic-gate new_pub_objp->is_lib_obj = B_FALSE;
15847c478bd9Sstevel@tonic-gate new_pub_objp->k_handle = obj_kp.kp_public_handle;
15857c478bd9Sstevel@tonic-gate new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
15867c478bd9Sstevel@tonic-gate new_pub_objp->extra_attrlistp = NULL;
15877c478bd9Sstevel@tonic-gate
15887c478bd9Sstevel@tonic-gate if (is_pri_obj1)
15897c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
15907c478bd9Sstevel@tonic-gate else
15917c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
15927c478bd9Sstevel@tonic-gate
15937c478bd9Sstevel@tonic-gate if (is_token_obj1)
15947c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask |= TOKEN_BOOL_ON;
15957c478bd9Sstevel@tonic-gate else
15967c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
15977c478bd9Sstevel@tonic-gate
15987c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
15997c478bd9Sstevel@tonic-gate new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
16007c478bd9Sstevel@tonic-gate
16017c478bd9Sstevel@tonic-gate /*
1602034448feSmcpowers * Store the kernel private key handle into the private key
1603034448feSmcpowers * object and finish the private key object initialization.
16047c478bd9Sstevel@tonic-gate */
16057c478bd9Sstevel@tonic-gate new_pri_objp->is_lib_obj = B_FALSE;
16067c478bd9Sstevel@tonic-gate new_pri_objp->k_handle = obj_kp.kp_private_handle;
16077c478bd9Sstevel@tonic-gate new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
16087c478bd9Sstevel@tonic-gate new_pri_objp->extra_attrlistp = NULL;
16097c478bd9Sstevel@tonic-gate
16107c478bd9Sstevel@tonic-gate if (is_pri_obj2)
16117c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
16127c478bd9Sstevel@tonic-gate else
16137c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
16147c478bd9Sstevel@tonic-gate
16157c478bd9Sstevel@tonic-gate if (is_token_obj2)
16167c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask |= TOKEN_BOOL_ON;
16177c478bd9Sstevel@tonic-gate else
16187c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
16197c478bd9Sstevel@tonic-gate
1620034448feSmcpowers }
16217c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
16227c478bd9Sstevel@tonic-gate new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
16237c478bd9Sstevel@tonic-gate
16247c478bd9Sstevel@tonic-gate /*
16257c478bd9Sstevel@tonic-gate * Add the new pub/pri objects to the slot's token list if they are
16267c478bd9Sstevel@tonic-gate * token objects. Otherwise, add them to the session's object list.
16277c478bd9Sstevel@tonic-gate */
16287c478bd9Sstevel@tonic-gate if (is_token_obj1) { /* is_token_obj1 == is_token_obj2 */
16297c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid];
16307c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_pub_objp, pslot);
16317c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_pri_objp, pslot);
16327c478bd9Sstevel@tonic-gate } else {
16337c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_pub_objp, session_p);
16347c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_pri_objp, session_p);
16357c478bd9Sstevel@tonic-gate }
16367c478bd9Sstevel@tonic-gate
16377c478bd9Sstevel@tonic-gate *phPublicKey = (CK_OBJECT_HANDLE)new_pub_objp;
16387c478bd9Sstevel@tonic-gate *phPrivateKey = (CK_OBJECT_HANDLE)new_pri_objp;
16397c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
16407c478bd9Sstevel@tonic-gate return (rv);
16417c478bd9Sstevel@tonic-gate
16427c478bd9Sstevel@tonic-gate failed_exit:
16437c478bd9Sstevel@tonic-gate if (new_pub_objp != NULL) {
16447c478bd9Sstevel@tonic-gate (void) free(new_pub_objp);
16457c478bd9Sstevel@tonic-gate }
16467c478bd9Sstevel@tonic-gate if (new_pri_objp != NULL) {
16477c478bd9Sstevel@tonic-gate (void) free(new_pri_objp);
16487c478bd9Sstevel@tonic-gate }
16497c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
16507c478bd9Sstevel@tonic-gate return (rv);
16517c478bd9Sstevel@tonic-gate }
16527c478bd9Sstevel@tonic-gate
16537c478bd9Sstevel@tonic-gate
16547c478bd9Sstevel@tonic-gate CK_RV
C_WrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hWrappingKey,CK_OBJECT_HANDLE hKey,CK_BYTE_PTR pWrappedKey,CK_ULONG_PTR pulWrappedKeyLen)16557c478bd9Sstevel@tonic-gate C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
16567c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
16577c478bd9Sstevel@tonic-gate CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
16587c478bd9Sstevel@tonic-gate {
16597c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
16607c478bd9Sstevel@tonic-gate kernel_session_t *session_p;
16617c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE;
16627c478bd9Sstevel@tonic-gate kernel_object_t *wrappingkey_p;
16637c478bd9Sstevel@tonic-gate kernel_object_t *key_p;
16647c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type;
16657c478bd9Sstevel@tonic-gate crypto_object_wrap_key_t obj_wrapkey;
16667c478bd9Sstevel@tonic-gate int r;
16677c478bd9Sstevel@tonic-gate
16687c478bd9Sstevel@tonic-gate if (!kernel_initialized)
16697c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
16707c478bd9Sstevel@tonic-gate
16717c478bd9Sstevel@tonic-gate if (pulWrappedKeyLen == NULL || pMechanism == NULL) {
16727c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
16737c478bd9Sstevel@tonic-gate }
16747c478bd9Sstevel@tonic-gate
16757c478bd9Sstevel@tonic-gate /*
16767c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session
16777c478bd9Sstevel@tonic-gate * reference count.
16787c478bd9Sstevel@tonic-gate */
16797c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
16807c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
16817c478bd9Sstevel@tonic-gate return (rv);
16827c478bd9Sstevel@tonic-gate
16837c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */
16847c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
16857c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
16867c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
16877c478bd9Sstevel@tonic-gate return (rv);
16887c478bd9Sstevel@tonic-gate }
16897c478bd9Sstevel@tonic-gate
16907c478bd9Sstevel@tonic-gate /* Obtain the wrapping key object pointer. */
16917c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hWrappingKey, wrappingkey_p, rv);
16927c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
16937c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
16947c478bd9Sstevel@tonic-gate return (rv);
16957c478bd9Sstevel@tonic-gate }
16967c478bd9Sstevel@tonic-gate
16977c478bd9Sstevel@tonic-gate /* Obtain the to_be_wrapped key object pointer. */
16987c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hKey, key_p, rv);
16997c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
170001223cbaSmcpowers OBJ_REFRELE(wrappingkey_p);
17017c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
17027c478bd9Sstevel@tonic-gate return (rv);
17037c478bd9Sstevel@tonic-gate }
17047c478bd9Sstevel@tonic-gate
17057c478bd9Sstevel@tonic-gate /* Make the CRYPTO_OBJECT_WRAP_KEY ioctl call. */
17067c478bd9Sstevel@tonic-gate obj_wrapkey.wk_session = session_p->k_session;
17077c478bd9Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_type = k_mech_type;
17087c478bd9Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_param = pMechanism->pParameter;
17097c478bd9Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_param_len = pMechanism->ulParameterLen;
17107c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapping_key.ck_format = CRYPTO_KEY_REFERENCE;
17117c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapping_key.ck_obj_id = wrappingkey_p->k_handle;
17127c478bd9Sstevel@tonic-gate obj_wrapkey.wk_object_handle = key_p->k_handle;
17137c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapped_key_len = *pulWrappedKeyLen;
17147c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapped_key = (char *)pWrappedKey;
17157c478bd9Sstevel@tonic-gate
17167c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_WRAP_KEY, &obj_wrapkey)) < 0) {
17177c478bd9Sstevel@tonic-gate if (errno != EINTR)
17187c478bd9Sstevel@tonic-gate break;
17197c478bd9Sstevel@tonic-gate }
17207c478bd9Sstevel@tonic-gate if (r < 0) {
17217c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
17227c478bd9Sstevel@tonic-gate } else {
17237c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_wrapkey.wk_return_value);
17247c478bd9Sstevel@tonic-gate }
17257c478bd9Sstevel@tonic-gate
17267c478bd9Sstevel@tonic-gate /*
17277c478bd9Sstevel@tonic-gate * Besides rv == CKR_OK, we will set the value of pulWrappedKeyLen
17287c478bd9Sstevel@tonic-gate * when the applciation-supplied wrapped key buffer is too small.
17297c478bd9Sstevel@tonic-gate * The situation that the application only asks for the length of
17307c478bd9Sstevel@tonic-gate * the wrapped key is covered in rv == CKR_OK.
17317c478bd9Sstevel@tonic-gate */
17327c478bd9Sstevel@tonic-gate if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) {
17337c478bd9Sstevel@tonic-gate *pulWrappedKeyLen = obj_wrapkey.wk_wrapped_key_len;
17347c478bd9Sstevel@tonic-gate }
17357c478bd9Sstevel@tonic-gate
173601223cbaSmcpowers OBJ_REFRELE(key_p);
173701223cbaSmcpowers OBJ_REFRELE(wrappingkey_p);
17387c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
17397c478bd9Sstevel@tonic-gate return (rv);
17407c478bd9Sstevel@tonic-gate }
17417c478bd9Sstevel@tonic-gate
17427c478bd9Sstevel@tonic-gate
17437c478bd9Sstevel@tonic-gate CK_RV
C_UnwrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hUnwrappingKey,CK_BYTE_PTR pWrappedKey,CK_ULONG ulWrappedKeyLen,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)17447c478bd9Sstevel@tonic-gate C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
17457c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey,
17467c478bd9Sstevel@tonic-gate CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
17477c478bd9Sstevel@tonic-gate CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
17487c478bd9Sstevel@tonic-gate {
17497c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
17507c478bd9Sstevel@tonic-gate kernel_session_t *session_p;
17517c478bd9Sstevel@tonic-gate kernel_object_t *unwrappingkey_p;
17527c478bd9Sstevel@tonic-gate kernel_object_t *new_objp = NULL;
17537c478bd9Sstevel@tonic-gate kernel_slot_t *pslot;
17547c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE;
17557c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj;
17567c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE;
17577c478bd9Sstevel@tonic-gate CK_MECHANISM_INFO info;
17587c478bd9Sstevel@tonic-gate uint32_t k_mi_flags;
17597c478bd9Sstevel@tonic-gate CK_BYTE *clear_key_val = NULL;
17607c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen;
17617c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR newTemplate = NULL;
17627c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type;
17637c478bd9Sstevel@tonic-gate crypto_object_unwrap_key_t obj_unwrapkey;
17647c478bd9Sstevel@tonic-gate int r;
17657c478bd9Sstevel@tonic-gate
17667c478bd9Sstevel@tonic-gate if (!kernel_initialized)
17677c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
17687c478bd9Sstevel@tonic-gate
17697c478bd9Sstevel@tonic-gate if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL) {
17707c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
17717c478bd9Sstevel@tonic-gate }
17727c478bd9Sstevel@tonic-gate
17737c478bd9Sstevel@tonic-gate if ((pTemplate == NULL) && (ulAttributeCount != 0)) {
17747c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
17757c478bd9Sstevel@tonic-gate }
17767c478bd9Sstevel@tonic-gate
17777c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */
17787c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
17797c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
17807c478bd9Sstevel@tonic-gate return (rv);
17817c478bd9Sstevel@tonic-gate
17827c478bd9Sstevel@tonic-gate /* Obtain the wrapping key object pointer. */
17837c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hUnwrappingKey, unwrappingkey_p, rv);
17847c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
178501223cbaSmcpowers REFRELE(session_p, ses_lock_held);
178601223cbaSmcpowers return (rv);
17877c478bd9Sstevel@tonic-gate }
17887c478bd9Sstevel@tonic-gate
17897c478bd9Sstevel@tonic-gate /*
17907c478bd9Sstevel@tonic-gate * If the HW provider doesn't support C_UnwrapKey, we will try
17917c478bd9Sstevel@tonic-gate * to emulate it in the library.
17927c478bd9Sstevel@tonic-gate */
17937c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid];
1794034448feSmcpowers if ((!pslot->sl_func_list.fl_object_create) &&
1795034448feSmcpowers (!pslot->sl_func_list.fl_key_unwrap)) {
17967c478bd9Sstevel@tonic-gate rv = get_mechanism_info(pslot, pMechanism->mechanism, &info,
17977c478bd9Sstevel@tonic-gate &k_mi_flags);
17987c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
17997c478bd9Sstevel@tonic-gate goto failed_exit;
18007c478bd9Sstevel@tonic-gate }
18017c478bd9Sstevel@tonic-gate
18027c478bd9Sstevel@tonic-gate /*
18037c478bd9Sstevel@tonic-gate * If the mechanism flag doesn't have CKF_UNWRAP, and it's
18047c478bd9Sstevel@tonic-gate * an unwrapping of a secret key object, then help this
18057c478bd9Sstevel@tonic-gate * out with a decryption followed by an object creation.
18067c478bd9Sstevel@tonic-gate */
18077c478bd9Sstevel@tonic-gate if (!(k_mi_flags & CRYPTO_FG_UNWRAP) &&
18087c478bd9Sstevel@tonic-gate (k_mi_flags & CRYPTO_FG_DECRYPT) &&
18097c478bd9Sstevel@tonic-gate (is_secret_key_template(pTemplate, ulAttributeCount))) {
18107c478bd9Sstevel@tonic-gate
18117c478bd9Sstevel@tonic-gate /* First allocate space for the recovered key value */
18127c478bd9Sstevel@tonic-gate clear_key_val = malloc(ulWrappedKeyLen);
18137c478bd9Sstevel@tonic-gate if (clear_key_val == NULL) {
18147c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
18157c478bd9Sstevel@tonic-gate goto failed_exit;
18167c478bd9Sstevel@tonic-gate }
18177c478bd9Sstevel@tonic-gate
18187c478bd9Sstevel@tonic-gate rv = kernel_decrypt_init(session_p, unwrappingkey_p,
18197c478bd9Sstevel@tonic-gate pMechanism);
18207c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
18217c478bd9Sstevel@tonic-gate goto failed_exit;
18227c478bd9Sstevel@tonic-gate }
18237c478bd9Sstevel@tonic-gate
18247c478bd9Sstevel@tonic-gate ulDataLen = ulWrappedKeyLen;
18257c478bd9Sstevel@tonic-gate rv = kernel_decrypt(session_p, pWrappedKey,
18267c478bd9Sstevel@tonic-gate ulWrappedKeyLen, clear_key_val, &ulDataLen);
18277c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
18287c478bd9Sstevel@tonic-gate goto failed_exit;
18297c478bd9Sstevel@tonic-gate }
18307c478bd9Sstevel@tonic-gate
1831034448feSmcpowers newTemplate = grow_template(pTemplate, ulAttributeCount,
1832034448feSmcpowers ulAttributeCount + 1);
18337c478bd9Sstevel@tonic-gate if (newTemplate == NULL) {
18347c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
18357c478bd9Sstevel@tonic-gate goto failed_exit;
18367c478bd9Sstevel@tonic-gate }
1837034448feSmcpowers /* Now add the CKA_VALUE attribute to template */
18387c478bd9Sstevel@tonic-gate newTemplate[ulAttributeCount].type = CKA_VALUE;
18397c478bd9Sstevel@tonic-gate newTemplate[ulAttributeCount].pValue = clear_key_val;
18407c478bd9Sstevel@tonic-gate newTemplate[ulAttributeCount].ulValueLen = ulDataLen;
18417c478bd9Sstevel@tonic-gate
18427c478bd9Sstevel@tonic-gate /* Finally create the key, based on the new template */
18437c478bd9Sstevel@tonic-gate rv = kernel_add_object(newTemplate,
18447c478bd9Sstevel@tonic-gate ulAttributeCount + 1, phKey, session_p);
18457c478bd9Sstevel@tonic-gate (void) free(clear_key_val);
18467c478bd9Sstevel@tonic-gate (void) free(newTemplate);
184701223cbaSmcpowers OBJ_REFRELE(unwrappingkey_p);
18487c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
18497c478bd9Sstevel@tonic-gate return (rv);
18507c478bd9Sstevel@tonic-gate } else {
18517c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
18527c478bd9Sstevel@tonic-gate goto failed_exit;
18537c478bd9Sstevel@tonic-gate }
18547c478bd9Sstevel@tonic-gate }
18557c478bd9Sstevel@tonic-gate
18567c478bd9Sstevel@tonic-gate /*
18577c478bd9Sstevel@tonic-gate * If we come here, the HW provider must have registered the unwrapkey
18587c478bd9Sstevel@tonic-gate * entry. Therefore, the unwrap key will be performed in the HW
18597c478bd9Sstevel@tonic-gate * provider.
18607c478bd9Sstevel@tonic-gate */
18617c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
18627c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
18637c478bd9Sstevel@tonic-gate goto failed_exit;
18647c478bd9Sstevel@tonic-gate }
18657c478bd9Sstevel@tonic-gate
18667c478bd9Sstevel@tonic-gate /* Create an object wrapper for the new key in the library first */
18677c478bd9Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t));
18687c478bd9Sstevel@tonic-gate if (new_objp == NULL) {
18697c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
18707c478bd9Sstevel@tonic-gate goto failed_exit;
18717c478bd9Sstevel@tonic-gate }
18727c478bd9Sstevel@tonic-gate
18737c478bd9Sstevel@tonic-gate /* Process the attributes */
18747c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulAttributeCount,
18757c478bd9Sstevel@tonic-gate &obj_unwrapkey.uk_attributes, &is_token_obj);
18767c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
18777c478bd9Sstevel@tonic-gate goto failed_exit;
18787c478bd9Sstevel@tonic-gate }
18797c478bd9Sstevel@tonic-gate
18807c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */
18817c478bd9Sstevel@tonic-gate if (is_token_obj && session_p->ses_RO) {
18827c478bd9Sstevel@tonic-gate free_object_attributes(obj_unwrapkey.uk_attributes,
18837c478bd9Sstevel@tonic-gate ulAttributeCount);
18847c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY;
18857c478bd9Sstevel@tonic-gate goto failed_exit;
18867c478bd9Sstevel@tonic-gate }
18877c478bd9Sstevel@tonic-gate
18887c478bd9Sstevel@tonic-gate /* Make the CRYPTO_UNWRAP_KEY ioctl call. */
18897c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_session = session_p->k_session;
18907c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_type = k_mech_type;
18917c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_param = pMechanism->pParameter;
18927c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_param_len = pMechanism->ulParameterLen;
18937c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_unwrapping_key.ck_format = CRYPTO_KEY_REFERENCE;
18947c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_unwrapping_key.ck_obj_id = unwrappingkey_p->k_handle;
18957c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_wrapped_key = (char *)pWrappedKey;
18967c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_wrapped_key_len = ulWrappedKeyLen;
18977c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_count = ulAttributeCount;
18987c478bd9Sstevel@tonic-gate
18997c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_UNWRAP_KEY, &obj_unwrapkey)) < 0) {
19007c478bd9Sstevel@tonic-gate if (errno != EINTR)
19017c478bd9Sstevel@tonic-gate break;
19027c478bd9Sstevel@tonic-gate }
19037c478bd9Sstevel@tonic-gate if (r < 0) {
19047c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
19057c478bd9Sstevel@tonic-gate } else {
19067c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_unwrapkey.uk_return_value);
19077c478bd9Sstevel@tonic-gate }
19087c478bd9Sstevel@tonic-gate
19097c478bd9Sstevel@tonic-gate free_object_attributes(obj_unwrapkey.uk_attributes, ulAttributeCount);
19107c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
19117c478bd9Sstevel@tonic-gate goto failed_exit;
19127c478bd9Sstevel@tonic-gate }
19137c478bd9Sstevel@tonic-gate
19147c478bd9Sstevel@tonic-gate /* Get the CKA_PRIVATE value for the unwrapped key. */
19157c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_unwrapkey.uk_object_handle,
19167c478bd9Sstevel@tonic-gate &is_pri_obj);
19177c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
19187c478bd9Sstevel@tonic-gate goto failed_exit;
19197c478bd9Sstevel@tonic-gate }
19207c478bd9Sstevel@tonic-gate
19217c478bd9Sstevel@tonic-gate /*
19227c478bd9Sstevel@tonic-gate * Store the kernel object handle in the new key object wrapper and
19237c478bd9Sstevel@tonic-gate * initialize it.
19247c478bd9Sstevel@tonic-gate */
19257c478bd9Sstevel@tonic-gate new_objp->k_handle = obj_unwrapkey.uk_object_handle;
19267c478bd9Sstevel@tonic-gate new_objp->is_lib_obj = B_FALSE;
19277c478bd9Sstevel@tonic-gate new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
19287c478bd9Sstevel@tonic-gate new_objp->extra_attrlistp = NULL;
19297c478bd9Sstevel@tonic-gate
19307c478bd9Sstevel@tonic-gate if (is_pri_obj)
19317c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
19327c478bd9Sstevel@tonic-gate else
19337c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
19347c478bd9Sstevel@tonic-gate
19357c478bd9Sstevel@tonic-gate if (is_token_obj)
19367c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
19377c478bd9Sstevel@tonic-gate else
19387c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
19397c478bd9Sstevel@tonic-gate
19407c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
19417c478bd9Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
19427c478bd9Sstevel@tonic-gate
19437c478bd9Sstevel@tonic-gate /*
19447c478bd9Sstevel@tonic-gate * Add the new object to the slot's token object list if it is a
19457c478bd9Sstevel@tonic-gate * a token object. Otherwise, add it to the session's object list.
19467c478bd9Sstevel@tonic-gate */
19477c478bd9Sstevel@tonic-gate if (is_token_obj) {
19487c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid];
19497c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot);
19507c478bd9Sstevel@tonic-gate } else {
19517c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p);
19527c478bd9Sstevel@tonic-gate }
19537c478bd9Sstevel@tonic-gate
19547c478bd9Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp;
195501223cbaSmcpowers OBJ_REFRELE(unwrappingkey_p);
19567c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
19577c478bd9Sstevel@tonic-gate return (rv);
19587c478bd9Sstevel@tonic-gate
19597c478bd9Sstevel@tonic-gate failed_exit:
196001223cbaSmcpowers OBJ_REFRELE(unwrappingkey_p);
19617c478bd9Sstevel@tonic-gate if (new_objp != NULL)
19627c478bd9Sstevel@tonic-gate (void) free(new_objp);
19637c478bd9Sstevel@tonic-gate
19647c478bd9Sstevel@tonic-gate if (clear_key_val != NULL)
19657c478bd9Sstevel@tonic-gate (void) free(clear_key_val);
19667c478bd9Sstevel@tonic-gate
19677c478bd9Sstevel@tonic-gate if (newTemplate != NULL)
19687c478bd9Sstevel@tonic-gate (void) free(newTemplate);
19697c478bd9Sstevel@tonic-gate
19707c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
19717c478bd9Sstevel@tonic-gate return (rv);
19727c478bd9Sstevel@tonic-gate }
19737c478bd9Sstevel@tonic-gate
1974034448feSmcpowers /*
1975034448feSmcpowers * Get sufficient attributes from a base key to pass by value in a
1976034448feSmcpowers * crypto_key structure. Storage for attributes is allocated.
1977034448feSmcpowers * For EC public keys, it is CKA_EC_PARAMS and CKA_EC_POINT.
1978034448feSmcpowers * For EC private keys, it is CKA_EC_PARAMS and CKA_VALUE.
1979034448feSmcpowers */
1980034448feSmcpowers static int
get_base_key_attributes(kernel_object_t * base_key,crypto_key_t * key_by_value)1981034448feSmcpowers get_base_key_attributes(kernel_object_t *base_key, crypto_key_t *key_by_value)
1982034448feSmcpowers {
1983034448feSmcpowers CK_ATTRIBUTE tmp;
1984*77e5e96bSMark Powers crypto_object_attribute_t *attrs = NULL;
1985034448feSmcpowers biginteger_t *big;
1986*77e5e96bSMark Powers int i, count = 0, rv;
1987034448feSmcpowers
1988034448feSmcpowers switch (base_key->key_type) {
1989034448feSmcpowers case CKK_EC:
1990*77e5e96bSMark Powers count = 2;
1991*77e5e96bSMark Powers attrs = malloc(count * sizeof (crypto_object_attribute_t));
1992034448feSmcpowers if (attrs == NULL) {
1993034448feSmcpowers rv = CKR_HOST_MEMORY;
1994034448feSmcpowers goto out;
1995034448feSmcpowers }
1996*77e5e96bSMark Powers bzero(attrs, count * sizeof (crypto_object_attribute_t));
1997034448feSmcpowers
1998034448feSmcpowers (void) pthread_mutex_lock(&base_key->object_mutex);
1999034448feSmcpowers
2000034448feSmcpowers if (!base_key->is_lib_obj) {
2001034448feSmcpowers rv = CRYPTO_ARGUMENTS_BAD;
2002034448feSmcpowers goto out;
2003034448feSmcpowers }
2004034448feSmcpowers
2005034448feSmcpowers if (base_key->class != CKO_PUBLIC_KEY &&
2006034448feSmcpowers base_key->class != CKO_PRIVATE_KEY) {
2007034448feSmcpowers rv = CRYPTO_ARGUMENTS_BAD;
2008034448feSmcpowers goto out;
2009034448feSmcpowers }
2010034448feSmcpowers
2011034448feSmcpowers /*
2012034448feSmcpowers * Both public and private EC keys should have
2013034448feSmcpowers * a CKA_EC_PARAMS attribute.
2014034448feSmcpowers */
2015034448feSmcpowers tmp.type = CKA_EC_PARAMS;
2016034448feSmcpowers tmp.pValue = NULL;
2017034448feSmcpowers
2018034448feSmcpowers /* get size of attribute */
2019034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp);
2020034448feSmcpowers if (rv != CKR_OK) {
2021034448feSmcpowers goto out;
2022034448feSmcpowers }
2023034448feSmcpowers
2024034448feSmcpowers tmp.pValue = malloc(tmp.ulValueLen);
2025034448feSmcpowers if (tmp.pValue == NULL) {
2026034448feSmcpowers rv = CKR_HOST_MEMORY;
2027034448feSmcpowers goto out;
2028034448feSmcpowers }
2029034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp);
2030034448feSmcpowers if (rv != CKR_OK) {
2031*77e5e96bSMark Powers free(tmp.pValue);
2032034448feSmcpowers goto out;
2033034448feSmcpowers }
2034034448feSmcpowers attrs[0].oa_type = tmp.type;
2035034448feSmcpowers attrs[0].oa_value = tmp.pValue;
2036034448feSmcpowers attrs[0].oa_value_len = tmp.ulValueLen;
2037034448feSmcpowers
2038034448feSmcpowers switch (base_key->class) {
2039034448feSmcpowers case CKO_PUBLIC_KEY:
2040034448feSmcpowers big = OBJ_PUB_EC_POINT(base_key);
2041034448feSmcpowers tmp.type = CKA_EC_POINT;
2042034448feSmcpowers break;
2043034448feSmcpowers
2044034448feSmcpowers case CKO_PRIVATE_KEY:
2045034448feSmcpowers big = OBJ_PRI_EC_VALUE(base_key);
2046034448feSmcpowers tmp.type = CKA_VALUE;
2047034448feSmcpowers break;
2048034448feSmcpowers
2049034448feSmcpowers default:
2050034448feSmcpowers rv = CKR_ATTRIBUTE_TYPE_INVALID;
2051034448feSmcpowers goto out;
2052034448feSmcpowers }
2053034448feSmcpowers tmp.ulValueLen = big->big_value_len;
2054034448feSmcpowers tmp.pValue = malloc(tmp.ulValueLen);
2055034448feSmcpowers if (tmp.pValue == NULL) {
2056034448feSmcpowers rv = CKR_HOST_MEMORY;
2057034448feSmcpowers goto out;
2058034448feSmcpowers }
2059034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp);
2060034448feSmcpowers if (rv != CKR_OK) {
2061*77e5e96bSMark Powers free(tmp.pValue);
2062034448feSmcpowers goto out;
2063034448feSmcpowers }
2064034448feSmcpowers attrs[1].oa_type = tmp.type;
2065034448feSmcpowers attrs[1].oa_value = tmp.pValue;
2066034448feSmcpowers attrs[1].oa_value_len = tmp.ulValueLen;
2067034448feSmcpowers key_by_value->ck_attrs = attrs;
2068034448feSmcpowers key_by_value->ck_count = 2;
2069034448feSmcpowers break;
2070034448feSmcpowers
2071034448feSmcpowers case CKK_DH:
2072*77e5e96bSMark Powers count = 3;
2073*77e5e96bSMark Powers attrs = malloc(count * sizeof (crypto_object_attribute_t));
2074034448feSmcpowers if (attrs == NULL) {
2075034448feSmcpowers rv = CKR_HOST_MEMORY;
2076034448feSmcpowers goto out;
2077034448feSmcpowers }
2078*77e5e96bSMark Powers bzero(attrs, count * sizeof (crypto_object_attribute_t));
2079034448feSmcpowers
2080034448feSmcpowers (void) pthread_mutex_lock(&base_key->object_mutex);
2081034448feSmcpowers
2082034448feSmcpowers if (!base_key->is_lib_obj) {
2083034448feSmcpowers rv = CRYPTO_ARGUMENTS_BAD;
2084034448feSmcpowers goto out;
2085034448feSmcpowers }
2086034448feSmcpowers
2087034448feSmcpowers if (base_key->class != CKO_PRIVATE_KEY) {
2088034448feSmcpowers rv = CRYPTO_ARGUMENTS_BAD;
2089034448feSmcpowers goto out;
2090034448feSmcpowers }
2091034448feSmcpowers tmp.type = CKA_BASE;
2092034448feSmcpowers tmp.pValue = NULL;
2093034448feSmcpowers
2094034448feSmcpowers /* get size of attribute */
2095034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp);
2096034448feSmcpowers if (rv != CKR_OK) {
2097034448feSmcpowers goto out;
2098034448feSmcpowers }
2099034448feSmcpowers
2100034448feSmcpowers tmp.pValue = malloc(tmp.ulValueLen);
2101034448feSmcpowers if (tmp.pValue == NULL) {
2102034448feSmcpowers rv = CKR_HOST_MEMORY;
2103034448feSmcpowers goto out;
2104034448feSmcpowers }
2105034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp);
2106034448feSmcpowers if (rv != CKR_OK) {
2107*77e5e96bSMark Powers free(tmp.pValue);
2108034448feSmcpowers goto out;
2109034448feSmcpowers }
2110034448feSmcpowers attrs[0].oa_type = tmp.type;
2111034448feSmcpowers attrs[0].oa_value = tmp.pValue;
2112034448feSmcpowers attrs[0].oa_value_len = tmp.ulValueLen;
2113034448feSmcpowers
2114034448feSmcpowers tmp.type = CKA_PRIME;
2115034448feSmcpowers tmp.pValue = NULL;
2116034448feSmcpowers
2117034448feSmcpowers /* get size of attribute */
2118034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp);
2119034448feSmcpowers if (rv != CKR_OK) {
2120034448feSmcpowers goto out;
2121034448feSmcpowers }
2122034448feSmcpowers
2123034448feSmcpowers tmp.pValue = malloc(tmp.ulValueLen);
2124034448feSmcpowers if (tmp.pValue == NULL) {
2125034448feSmcpowers rv = CKR_HOST_MEMORY;
2126034448feSmcpowers goto out;
2127034448feSmcpowers }
2128034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp);
2129034448feSmcpowers if (rv != CKR_OK) {
2130*77e5e96bSMark Powers free(tmp.pValue);
2131034448feSmcpowers goto out;
2132034448feSmcpowers }
2133034448feSmcpowers attrs[1].oa_type = tmp.type;
2134034448feSmcpowers attrs[1].oa_value = tmp.pValue;
2135034448feSmcpowers attrs[1].oa_value_len = tmp.ulValueLen;
2136034448feSmcpowers
2137*77e5e96bSMark Powers big = OBJ_PRI_DH_VALUE(base_key);
2138034448feSmcpowers tmp.type = CKA_VALUE;
2139034448feSmcpowers
2140034448feSmcpowers tmp.ulValueLen = big->big_value_len;
2141034448feSmcpowers tmp.pValue = malloc(tmp.ulValueLen);
2142034448feSmcpowers if (tmp.pValue == NULL) {
2143034448feSmcpowers rv = CKR_HOST_MEMORY;
2144034448feSmcpowers goto out;
2145034448feSmcpowers }
2146034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp);
2147034448feSmcpowers if (rv != CKR_OK) {
2148*77e5e96bSMark Powers free(tmp.pValue);
2149034448feSmcpowers goto out;
2150034448feSmcpowers }
2151034448feSmcpowers attrs[2].oa_type = tmp.type;
2152034448feSmcpowers attrs[2].oa_value = tmp.pValue;
2153034448feSmcpowers attrs[2].oa_value_len = tmp.ulValueLen;
2154034448feSmcpowers key_by_value->ck_attrs = attrs;
2155034448feSmcpowers key_by_value->ck_count = 3;
2156034448feSmcpowers break;
2157034448feSmcpowers
2158034448feSmcpowers default:
2159034448feSmcpowers rv = CKR_ATTRIBUTE_TYPE_INVALID;
2160034448feSmcpowers goto out;
2161034448feSmcpowers }
2162034448feSmcpowers (void) pthread_mutex_unlock(&base_key->object_mutex);
2163034448feSmcpowers return (CKR_OK);
2164034448feSmcpowers
2165034448feSmcpowers out:
2166034448feSmcpowers (void) pthread_mutex_unlock(&base_key->object_mutex);
2167*77e5e96bSMark Powers if (attrs != NULL) {
2168*77e5e96bSMark Powers for (i = 0; i < count; i++) {
2169*77e5e96bSMark Powers if (attrs[i].oa_value != NULL)
2170*77e5e96bSMark Powers free(attrs[i].oa_value);
2171*77e5e96bSMark Powers }
2172*77e5e96bSMark Powers free(attrs);
2173*77e5e96bSMark Powers }
2174034448feSmcpowers return (rv);
2175034448feSmcpowers }
2176034448feSmcpowers
2177034448feSmcpowers CK_RV
derive_key_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * basekey_p,kernel_object_t * new_objp)2178034448feSmcpowers derive_key_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate,
2179034448feSmcpowers CK_ULONG ulAttributeCount, kernel_session_t *session_p,
2180034448feSmcpowers crypto_mech_type_t k_mech_type, kernel_object_t *basekey_p,
2181034448feSmcpowers kernel_object_t *new_objp)
2182034448feSmcpowers {
2183034448feSmcpowers crypto_nostore_derive_key_t obj_ndk;
2184034448feSmcpowers char *key_buf = NULL;
2185034448feSmcpowers CK_ATTRIBUTE_PTR newTemplate = NULL;
2186034448feSmcpowers CK_BBOOL is_token_obj = FALSE;
2187034448feSmcpowers CK_RV rv = CKR_OK;
2188034448feSmcpowers CK_ULONG secret_class = CKO_SECRET_KEY;
2189034448feSmcpowers ulong_t key_len = 0;
2190034448feSmcpowers uint_t attr_count = 0;
2191034448feSmcpowers boolean_t removed;
2192034448feSmcpowers boolean_t has_class;
2193034448feSmcpowers int r, n;
2194034448feSmcpowers
2195034448feSmcpowers obj_ndk.ndk_in_count = 0;
2196034448feSmcpowers obj_ndk.ndk_out_count = 0;
2197034448feSmcpowers obj_ndk.ndk_base_key.ck_count = 0;
2198034448feSmcpowers
2199034448feSmcpowers rv = get_key_len_from_template(pMechanism, pTemplate, ulAttributeCount,
2200034448feSmcpowers basekey_p, &key_len);
2201034448feSmcpowers if (rv != CKR_OK) {
2202034448feSmcpowers goto failed_exit;
2203034448feSmcpowers }
2204034448feSmcpowers
2205034448feSmcpowers if ((key_buf = malloc(key_len)) == NULL) {
2206034448feSmcpowers rv = CKR_HOST_MEMORY;
2207034448feSmcpowers goto failed_exit;
2208034448feSmcpowers }
2209034448feSmcpowers
2210034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pTemplate,
2211034448feSmcpowers ulAttributeCount);
2212034448feSmcpowers
2213034448feSmcpowers attr_count = ulAttributeCount + 1;
2214034448feSmcpowers if (!has_class)
2215034448feSmcpowers attr_count++;
2216034448feSmcpowers
2217034448feSmcpowers newTemplate = grow_template(pTemplate, ulAttributeCount, attr_count);
2218034448feSmcpowers if (newTemplate == NULL) {
2219034448feSmcpowers rv = CKR_HOST_MEMORY;
2220034448feSmcpowers goto failed_exit;
2221034448feSmcpowers }
2222034448feSmcpowers
2223034448feSmcpowers n = ulAttributeCount;
2224034448feSmcpowers if (!has_class) {
2225034448feSmcpowers newTemplate[n].type = CKA_CLASS;
2226034448feSmcpowers newTemplate[n].pValue = (caddr_t)&secret_class;
2227034448feSmcpowers newTemplate[n].ulValueLen = sizeof (secret_class);
2228034448feSmcpowers n++;
2229034448feSmcpowers }
2230034448feSmcpowers
2231034448feSmcpowers /* Add CKA_VALUE to the template */
2232034448feSmcpowers newTemplate[n].type = CKA_VALUE;
2233034448feSmcpowers newTemplate[n].pValue = (caddr_t)key_buf;
2234034448feSmcpowers newTemplate[n].ulValueLen = key_len;
2235034448feSmcpowers
2236034448feSmcpowers rv = process_object_attributes(newTemplate, attr_count - 1,
2237034448feSmcpowers &obj_ndk.ndk_in_attributes, &is_token_obj);
2238034448feSmcpowers if (rv != CKR_OK) {
2239034448feSmcpowers goto failed_exit;
2240034448feSmcpowers }
2241*77e5e96bSMark Powers obj_ndk.ndk_in_count = attr_count - 1;
2242034448feSmcpowers
2243034448feSmcpowers rv = process_object_attributes(&newTemplate[attr_count - 1],
2244034448feSmcpowers 1, &obj_ndk.ndk_out_attributes, &is_token_obj);
2245034448feSmcpowers if (rv != CKR_OK) {
2246034448feSmcpowers goto failed_exit;
2247034448feSmcpowers }
2248*77e5e96bSMark Powers obj_ndk.ndk_out_count = 1;
2249034448feSmcpowers
2250034448feSmcpowers /* Cannot create a token object with a READ-ONLY session. */
2251034448feSmcpowers if (is_token_obj && session_p->ses_RO) {
2252034448feSmcpowers rv = CKR_SESSION_READ_ONLY;
2253034448feSmcpowers goto failed_exit;
2254034448feSmcpowers }
2255034448feSmcpowers
2256034448feSmcpowers obj_ndk.ndk_session = session_p->k_session;
2257034448feSmcpowers obj_ndk.ndk_mechanism.cm_type = k_mech_type;
2258034448feSmcpowers obj_ndk.ndk_mechanism.cm_param = pMechanism->pParameter;
2259034448feSmcpowers obj_ndk.ndk_mechanism.cm_param_len = pMechanism->ulParameterLen;
2260034448feSmcpowers
2261034448feSmcpowers /*
2262034448feSmcpowers * Obtain the attributes of base key and pass them by value.
2263034448feSmcpowers */
2264034448feSmcpowers rv = get_base_key_attributes(basekey_p, &obj_ndk.ndk_base_key);
2265034448feSmcpowers if (rv != CKR_OK) {
2266034448feSmcpowers goto failed_exit;
2267034448feSmcpowers }
2268034448feSmcpowers
2269034448feSmcpowers obj_ndk.ndk_base_key.ck_format = CRYPTO_KEY_ATTR_LIST;
2270034448feSmcpowers
2271034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_DERIVE_KEY,
2272034448feSmcpowers &obj_ndk)) < 0) {
2273034448feSmcpowers if (errno != EINTR)
2274034448feSmcpowers break;
2275034448feSmcpowers }
2276034448feSmcpowers if (r < 0) {
2277034448feSmcpowers rv = CKR_FUNCTION_FAILED;
2278034448feSmcpowers } else {
2279034448feSmcpowers rv = crypto2pkcs11_error_number(obj_ndk.ndk_return_value);
2280034448feSmcpowers }
2281034448feSmcpowers free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count);
2282034448feSmcpowers free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs,
2283034448feSmcpowers &obj_ndk.ndk_base_key.ck_count);
2284034448feSmcpowers if (rv != CKR_OK) {
2285034448feSmcpowers goto failed_exit;
2286034448feSmcpowers }
2287034448feSmcpowers
2288034448feSmcpowers rv = get_object_attributes(&newTemplate[attr_count - 1],
2289034448feSmcpowers 1, obj_ndk.ndk_out_attributes);
2290034448feSmcpowers free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count);
2291034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
2292034448feSmcpowers goto failed_exit;
2293034448feSmcpowers }
2294034448feSmcpowers
2295034448feSmcpowers removed = remove_one_attribute(newTemplate, CKA_VALUE_LEN,
2296034448feSmcpowers attr_count, B_FALSE);
2297034448feSmcpowers
2298034448feSmcpowers rv = kernel_build_object(newTemplate, removed ? attr_count - 1 :
2299034448feSmcpowers attr_count, new_objp, session_p, KERNEL_GEN_KEY);
2300034448feSmcpowers if (rv != CRYPTO_SUCCESS) {
2301034448feSmcpowers goto failed_exit;
2302034448feSmcpowers }
2303034448feSmcpowers
2304034448feSmcpowers free(key_buf);
2305034448feSmcpowers free(newTemplate);
2306034448feSmcpowers new_objp->is_lib_obj = B_TRUE;
2307034448feSmcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
2308034448feSmcpowers return (CKR_OK);
2309034448feSmcpowers
2310034448feSmcpowers failed_exit:
2311034448feSmcpowers if (key_buf != NULL)
2312034448feSmcpowers free(key_buf);
2313034448feSmcpowers if (newTemplate != NULL)
2314034448feSmcpowers free(newTemplate);
2315034448feSmcpowers free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count);
2316034448feSmcpowers free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count);
2317034448feSmcpowers free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs,
2318034448feSmcpowers &obj_ndk.ndk_base_key.ck_count);
2319034448feSmcpowers return (rv);
2320034448feSmcpowers }
23217c478bd9Sstevel@tonic-gate
23227c478bd9Sstevel@tonic-gate CK_RV
C_DeriveKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hBaseKey,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)23237c478bd9Sstevel@tonic-gate C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
23247c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
23257c478bd9Sstevel@tonic-gate CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
23267c478bd9Sstevel@tonic-gate {
23277c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
23287c478bd9Sstevel@tonic-gate kernel_session_t *session_p;
23297c478bd9Sstevel@tonic-gate kernel_object_t *basekey_p;
23307c478bd9Sstevel@tonic-gate kernel_object_t *new_objp;
23317c478bd9Sstevel@tonic-gate kernel_slot_t *pslot;
23327c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE;
23337c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj;
23347c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE;
23357c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type;
23367c478bd9Sstevel@tonic-gate int r;
23377c478bd9Sstevel@tonic-gate
23387c478bd9Sstevel@tonic-gate if (!kernel_initialized)
23397c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
23407c478bd9Sstevel@tonic-gate
23417c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */
23427c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
23437c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
23447c478bd9Sstevel@tonic-gate return (rv);
23457c478bd9Sstevel@tonic-gate
234660722cc8Sizick if (pMechanism == NULL) {
234701223cbaSmcpowers REFRELE(session_p, ses_lock_held);
234801223cbaSmcpowers return (CKR_ARGUMENTS_BAD);
23497c478bd9Sstevel@tonic-gate }
23507c478bd9Sstevel@tonic-gate
23517c478bd9Sstevel@tonic-gate if ((pTemplate == NULL && ulAttributeCount != 0) ||
23527c478bd9Sstevel@tonic-gate (pTemplate != NULL && ulAttributeCount == 0)) {
235301223cbaSmcpowers REFRELE(session_p, ses_lock_held);
235401223cbaSmcpowers return (CKR_ARGUMENTS_BAD);
23557c478bd9Sstevel@tonic-gate }
23567c478bd9Sstevel@tonic-gate
23577c478bd9Sstevel@tonic-gate /* Obtain the base key object pointer. */
23587c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hBaseKey, basekey_p, rv);
23597c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
236001223cbaSmcpowers REFRELE(session_p, ses_lock_held);
236101223cbaSmcpowers return (rv);
23627c478bd9Sstevel@tonic-gate }
23637c478bd9Sstevel@tonic-gate
23647c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */
23657c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
23667c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
23677c478bd9Sstevel@tonic-gate goto failed_exit;
23687c478bd9Sstevel@tonic-gate }
23697c478bd9Sstevel@tonic-gate
23707c478bd9Sstevel@tonic-gate /* Create an object wrapper in the library for the generated key. */
23717c478bd9Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t));
23727c478bd9Sstevel@tonic-gate if (new_objp == NULL) {
23737c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
23747c478bd9Sstevel@tonic-gate goto failed_exit;
23757c478bd9Sstevel@tonic-gate }
23767c478bd9Sstevel@tonic-gate
2377034448feSmcpowers /*
2378034448feSmcpowers * Special Case: if token does not support object creation,
2379034448feSmcpowers * but does support key derivation by value, then create a session
2380034448feSmcpowers * object and initialize with values returned by token.
2381034448feSmcpowers */
2382034448feSmcpowers pslot = slot_table[session_p->ses_slotid];
2383034448feSmcpowers if (!pslot->sl_func_list.fl_object_create) {
2384034448feSmcpowers rv = derive_key_by_value(pMechanism, pTemplate,
2385034448feSmcpowers ulAttributeCount, session_p, k_mech_type, basekey_p,
2386034448feSmcpowers new_objp);
2387034448feSmcpowers if (rv != CKR_OK)
2388034448feSmcpowers goto failed_exit;
2389034448feSmcpowers } else {
2390034448feSmcpowers crypto_derive_key_t obj_dk;
2391034448feSmcpowers
23927c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulAttributeCount,
23937c478bd9Sstevel@tonic-gate &obj_dk.dk_attributes, &is_token_obj);
23947c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
23957c478bd9Sstevel@tonic-gate goto failed_exit;
23967c478bd9Sstevel@tonic-gate }
23977c478bd9Sstevel@tonic-gate
23987c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */
23997c478bd9Sstevel@tonic-gate if (is_token_obj && session_p->ses_RO) {
2400034448feSmcpowers free_object_attributes(obj_dk.dk_attributes,
2401034448feSmcpowers ulAttributeCount);
24027c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY;
24037c478bd9Sstevel@tonic-gate goto failed_exit;
24047c478bd9Sstevel@tonic-gate }
24057c478bd9Sstevel@tonic-gate
24067c478bd9Sstevel@tonic-gate obj_dk.dk_session = session_p->k_session;
24077c478bd9Sstevel@tonic-gate obj_dk.dk_mechanism.cm_type = k_mech_type;
24087c478bd9Sstevel@tonic-gate obj_dk.dk_mechanism.cm_param = pMechanism->pParameter;
24097c478bd9Sstevel@tonic-gate obj_dk.dk_mechanism.cm_param_len = pMechanism->ulParameterLen;
24107c478bd9Sstevel@tonic-gate obj_dk.dk_base_key.ck_format = CRYPTO_KEY_REFERENCE;
24117c478bd9Sstevel@tonic-gate obj_dk.dk_base_key.ck_obj_id = basekey_p->k_handle;
24127c478bd9Sstevel@tonic-gate obj_dk.dk_count = ulAttributeCount;
24137c478bd9Sstevel@tonic-gate
24147c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_DERIVE_KEY, &obj_dk)) < 0) {
24157c478bd9Sstevel@tonic-gate if (errno != EINTR)
24167c478bd9Sstevel@tonic-gate break;
24177c478bd9Sstevel@tonic-gate }
24187c478bd9Sstevel@tonic-gate if (r < 0) {
24197c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
24207c478bd9Sstevel@tonic-gate } else {
24217c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_dk.dk_return_value);
24227c478bd9Sstevel@tonic-gate }
24237c478bd9Sstevel@tonic-gate
24247c478bd9Sstevel@tonic-gate free_object_attributes(obj_dk.dk_attributes, ulAttributeCount);
24257c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
24267c478bd9Sstevel@tonic-gate goto failed_exit;
24277c478bd9Sstevel@tonic-gate }
24287c478bd9Sstevel@tonic-gate
24297c478bd9Sstevel@tonic-gate /* Get the CKA_PRIVATE value for the derived key. */
24307c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_dk.dk_object_handle,
24317c478bd9Sstevel@tonic-gate &is_pri_obj);
24327c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
24337c478bd9Sstevel@tonic-gate goto failed_exit;
24347c478bd9Sstevel@tonic-gate }
24357c478bd9Sstevel@tonic-gate
24367c478bd9Sstevel@tonic-gate /*
2437034448feSmcpowers * Store the kernel object handle into the new derived key
2438034448feSmcpowers * object and finish the object initialization.
24397c478bd9Sstevel@tonic-gate */
24407c478bd9Sstevel@tonic-gate new_objp->is_lib_obj = B_FALSE;
24417c478bd9Sstevel@tonic-gate new_objp->k_handle = obj_dk.dk_object_handle;
24427c478bd9Sstevel@tonic-gate new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
24437c478bd9Sstevel@tonic-gate new_objp->extra_attrlistp = NULL;
24447c478bd9Sstevel@tonic-gate
24457c478bd9Sstevel@tonic-gate if (is_pri_obj)
24467c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
24477c478bd9Sstevel@tonic-gate else
24487c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
24497c478bd9Sstevel@tonic-gate
24507c478bd9Sstevel@tonic-gate if (is_token_obj)
24517c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
24527c478bd9Sstevel@tonic-gate else
24537c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
2454034448feSmcpowers }
24557c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
24567c478bd9Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
24577c478bd9Sstevel@tonic-gate
24587c478bd9Sstevel@tonic-gate /*
24597c478bd9Sstevel@tonic-gate * Add the new derived object to the slot's token list if it is a
24607c478bd9Sstevel@tonic-gate * token object. Otherwise, add it to the session's object list.
24617c478bd9Sstevel@tonic-gate */
24627c478bd9Sstevel@tonic-gate if (is_token_obj) {
24637c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid];
24647c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot);
24657c478bd9Sstevel@tonic-gate } else {
24667c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p);
24677c478bd9Sstevel@tonic-gate }
24687c478bd9Sstevel@tonic-gate
24697c478bd9Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp;
247001223cbaSmcpowers OBJ_REFRELE(basekey_p);
24717c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
24727c478bd9Sstevel@tonic-gate return (rv);
24737c478bd9Sstevel@tonic-gate
24747c478bd9Sstevel@tonic-gate failed_exit:
247501223cbaSmcpowers OBJ_REFRELE(basekey_p);
24767c478bd9Sstevel@tonic-gate if (new_objp != NULL) {
24777c478bd9Sstevel@tonic-gate (void) free(new_objp);
24787c478bd9Sstevel@tonic-gate }
24797c478bd9Sstevel@tonic-gate
24807c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
24817c478bd9Sstevel@tonic-gate return (rv);
24827c478bd9Sstevel@tonic-gate }
2483