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