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