10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*4219Smcpowers * Common Development and Distribution License (the "License"). 6*4219Smcpowers * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*4219Smcpowers * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <strings.h> 290Sstevel@tonic-gate #include <errno.h> 300Sstevel@tonic-gate #include <security/cryptoki.h> 310Sstevel@tonic-gate #include <sys/crypto/ioctl.h> 320Sstevel@tonic-gate #include "kernelGlobal.h" 330Sstevel@tonic-gate #include "kernelSession.h" 340Sstevel@tonic-gate #include "kernelObject.h" 350Sstevel@tonic-gate 360Sstevel@tonic-gate static boolean_t 37*4219Smcpowers attribute_in_template(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR t, CK_ULONG cnt) 38*4219Smcpowers { 39*4219Smcpowers int i; 40*4219Smcpowers 41*4219Smcpowers for (i = 0; i < cnt; i++) { 42*4219Smcpowers if (t[i].type == type) 43*4219Smcpowers return (B_TRUE); 44*4219Smcpowers } 45*4219Smcpowers return (B_FALSE); 46*4219Smcpowers } 47*4219Smcpowers 48*4219Smcpowers /* 49*4219Smcpowers * This routine returns modulus bytes rounded up to the nearest 8 byte 50*4219Smcpowers * chunk. This is so we don't have to pass in max sized buffers for 51*4219Smcpowers * returned attributes. Every unnecessary byte that we pass in results 52*4219Smcpowers * in a kernel allocation. 53*4219Smcpowers */ 54*4219Smcpowers static ulong_t 55*4219Smcpowers get_modulus_bytes(CK_ATTRIBUTE_PTR t, CK_ULONG cnt) 56*4219Smcpowers { 57*4219Smcpowers CK_ULONG modulus_len; 58*4219Smcpowers int i; 59*4219Smcpowers 60*4219Smcpowers for (i = 0; i < cnt; i++) { 61*4219Smcpowers if (t[i].type == CKA_MODULUS_BITS) { 62*4219Smcpowers get_ulong_attr_from_template(&modulus_len, &t[i]); 63*4219Smcpowers /* convert from bit length to byte length */ 64*4219Smcpowers modulus_len = (modulus_len - 1) / 64 + 1; 65*4219Smcpowers return (modulus_len * 8); 66*4219Smcpowers } 67*4219Smcpowers } 68*4219Smcpowers return (0); 69*4219Smcpowers } 70*4219Smcpowers 71*4219Smcpowers /* 72*4219Smcpowers * Remove specified attribute from array. Storage for the attribute's 73*4219Smcpowers * value is freed if 'free_attr' is TRUE. Attributes are shifted so they are 74*4219Smcpowers * contiguous within the array, i.e. the next attribute is shifted into 75*4219Smcpowers * the position of the removed attribute. Returns TRUE if specified 76*4219Smcpowers * attribute is removed. 77*4219Smcpowers */ 78*4219Smcpowers static boolean_t 79*4219Smcpowers remove_one_attribute(CK_ATTRIBUTE_PTR t, CK_ULONG type, uint_t count, 80*4219Smcpowers boolean_t free_attr) 81*4219Smcpowers { 82*4219Smcpowers int i, j; 83*4219Smcpowers 84*4219Smcpowers for (i = 0, j = 0; i < count; i++) { 85*4219Smcpowers if (t[i].type == type) { 86*4219Smcpowers if (free_attr) { 87*4219Smcpowers free(t[i].pValue); 88*4219Smcpowers } 89*4219Smcpowers continue; 90*4219Smcpowers } 91*4219Smcpowers if (i != j) { 92*4219Smcpowers t[j].type = t[i].type; 93*4219Smcpowers t[j].pValue = t[i].pValue; 94*4219Smcpowers t[j].ulValueLen = t[i].ulValueLen; 95*4219Smcpowers } 96*4219Smcpowers j++; 97*4219Smcpowers } 98*4219Smcpowers if (j == count) 99*4219Smcpowers return (B_FALSE); 100*4219Smcpowers 101*4219Smcpowers /* safety */ 102*4219Smcpowers t[j].pValue = NULL; 103*4219Smcpowers t[j].ulValueLen = 0; 104*4219Smcpowers return (B_TRUE); 105*4219Smcpowers } 106*4219Smcpowers 107*4219Smcpowers static boolean_t 1080Sstevel@tonic-gate is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount) 1090Sstevel@tonic-gate { 1100Sstevel@tonic-gate int i; 1110Sstevel@tonic-gate for (i = 0; i < ulAttributeCount; i++) { 1120Sstevel@tonic-gate if (pTemplate[i].type == CKA_CLASS && 1130Sstevel@tonic-gate *(CK_OBJECT_CLASS *)(pTemplate[i].pValue) == 1140Sstevel@tonic-gate CKO_SECRET_KEY) 1150Sstevel@tonic-gate return (B_TRUE); 1160Sstevel@tonic-gate } 1170Sstevel@tonic-gate return (B_FALSE); 1180Sstevel@tonic-gate } 1190Sstevel@tonic-gate 120*4219Smcpowers /* 121*4219Smcpowers * Allocate a template with space for new_count entries and copy the 122*4219Smcpowers * specified template into the new template. 123*4219Smcpowers */ 124*4219Smcpowers static CK_ATTRIBUTE_PTR 125*4219Smcpowers grow_template(CK_ATTRIBUTE_PTR old_template, CK_ULONG old_count, 126*4219Smcpowers CK_ULONG new_count) 127*4219Smcpowers { 128*4219Smcpowers CK_ATTRIBUTE_PTR new_template; 129*4219Smcpowers 130*4219Smcpowers new_template = malloc(new_count * sizeof (CK_ATTRIBUTE)); 131*4219Smcpowers if (new_template != NULL) 132*4219Smcpowers bcopy(old_template, new_template, 133*4219Smcpowers old_count * sizeof (CK_ATTRIBUTE)); 134*4219Smcpowers return (new_template); 135*4219Smcpowers } 136*4219Smcpowers 137*4219Smcpowers /* 138*4219Smcpowers * For fixed length keys such as DES, return the length based on 139*4219Smcpowers * the key type. For variable length keys such as AES, take the 140*4219Smcpowers * length from the CKA_VALUE_LEN attribute. 141*4219Smcpowers */ 142*4219Smcpowers static int 143*4219Smcpowers get_key_len_from_template(CK_MECHANISM_PTR pMechanism, 144*4219Smcpowers CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, 145*4219Smcpowers kernel_object_t *basekey_p, ulong_t *key_len) 146*4219Smcpowers { 147*4219Smcpowers boolean_t fixed_len_key = B_FALSE; 148*4219Smcpowers ulong_t key_type; 149*4219Smcpowers int i; 150*4219Smcpowers 151*4219Smcpowers for (i = 0; i < ulAttributeCount; i++) { 152*4219Smcpowers if (pTemplate[i].type == CKA_KEY_TYPE) { 153*4219Smcpowers get_ulong_attr_from_template(&key_type, &pTemplate[i]); 154*4219Smcpowers break; 155*4219Smcpowers } 156*4219Smcpowers } 157*4219Smcpowers /* CKA_KEY_TYPE must be present */ 158*4219Smcpowers if (i == ulAttributeCount) 159*4219Smcpowers return (CKR_TEMPLATE_INCOMPLETE); 160*4219Smcpowers 161*4219Smcpowers switch (key_type) { 162*4219Smcpowers case CKK_DES: 163*4219Smcpowers *key_len = 8; 164*4219Smcpowers fixed_len_key = B_TRUE; 165*4219Smcpowers break; 166*4219Smcpowers case CKK_DES3: 167*4219Smcpowers *key_len = 24; 168*4219Smcpowers fixed_len_key = B_TRUE; 169*4219Smcpowers break; 170*4219Smcpowers case CKK_AES: 171*4219Smcpowers case CKK_BLOWFISH: 172*4219Smcpowers for (i = 0; i < ulAttributeCount; i++) { 173*4219Smcpowers if (pTemplate[i].type == CKA_VALUE_LEN) { 174*4219Smcpowers get_ulong_attr_from_template(key_len, 175*4219Smcpowers &pTemplate[i]); 176*4219Smcpowers break; 177*4219Smcpowers } 178*4219Smcpowers } 179*4219Smcpowers /* CKA_VALUE_LEN must be present */ 180*4219Smcpowers if (i == ulAttributeCount) 181*4219Smcpowers return (CKR_TEMPLATE_INCOMPLETE); 182*4219Smcpowers break; 183*4219Smcpowers case CKK_GENERIC_SECRET: 184*4219Smcpowers /* 185*4219Smcpowers * The key will not be truncated, so we need to 186*4219Smcpowers * get the max length for the mechanism. 187*4219Smcpowers */ 188*4219Smcpowers if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE) { 189*4219Smcpowers CK_ATTRIBUTE tmp; 190*4219Smcpowers 191*4219Smcpowers tmp.type = CKA_PRIME; 192*4219Smcpowers tmp.pValue = NULL; 193*4219Smcpowers 194*4219Smcpowers /* get size of attribute */ 195*4219Smcpowers if (kernel_get_attribute(basekey_p, &tmp) != CKR_OK) { 196*4219Smcpowers return (CKR_ARGUMENTS_BAD); 197*4219Smcpowers } 198*4219Smcpowers *key_len = tmp.ulValueLen; 199*4219Smcpowers } else { 200*4219Smcpowers return (CKR_ARGUMENTS_BAD); 201*4219Smcpowers } 202*4219Smcpowers break; 203*4219Smcpowers default: 204*4219Smcpowers return (CKR_ATTRIBUTE_VALUE_INVALID); 205*4219Smcpowers } 206*4219Smcpowers 207*4219Smcpowers if (fixed_len_key && attribute_in_template(CKA_VALUE_LEN, 208*4219Smcpowers pTemplate, ulAttributeCount)) 209*4219Smcpowers return (CKR_TEMPLATE_INCONSISTENT); 210*4219Smcpowers 211*4219Smcpowers return (CKR_OK); 212*4219Smcpowers } 213*4219Smcpowers 214*4219Smcpowers /* find specified attribute src template and copy to dest */ 215*4219Smcpowers static int 216*4219Smcpowers copy_attribute(CK_ULONG type, CK_ATTRIBUTE_PTR src, CK_ULONG src_cnt, 217*4219Smcpowers CK_ATTRIBUTE_PTR dst) 218*4219Smcpowers { 219*4219Smcpowers int rv, i; 220*4219Smcpowers 221*4219Smcpowers for (i = 0; i < src_cnt; i++) { 222*4219Smcpowers if (src[i].type == type) { 223*4219Smcpowers rv = get_string_from_template(dst, &src[i]); 224*4219Smcpowers break; 225*4219Smcpowers } 226*4219Smcpowers } 227*4219Smcpowers /* 228*4219Smcpowers * The public template didn't have attribute. 229*4219Smcpowers */ 230*4219Smcpowers if (i == src_cnt) { 231*4219Smcpowers rv = CKR_TEMPLATE_INCOMPLETE; 232*4219Smcpowers } 233*4219Smcpowers return (rv); 234*4219Smcpowers } 235*4219Smcpowers 236*4219Smcpowers static void 237*4219Smcpowers free_attributes(caddr_t p, uint_t *countp) 238*4219Smcpowers { 239*4219Smcpowers if (*countp > 0) { 240*4219Smcpowers free_object_attributes(p, *countp); 241*4219Smcpowers *countp = 0; 242*4219Smcpowers } 243*4219Smcpowers } 244*4219Smcpowers 245*4219Smcpowers CK_RV 246*4219Smcpowers key_gen_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, 247*4219Smcpowers CK_ULONG ulCount, kernel_session_t *session_p, 248*4219Smcpowers crypto_mech_type_t k_mech_type, kernel_object_t *new_objp) 249*4219Smcpowers { 250*4219Smcpowers crypto_nostore_generate_key_t obj_ngk; 251*4219Smcpowers char *key_buf = NULL; 252*4219Smcpowers CK_ATTRIBUTE_PTR newTemplate = NULL; 253*4219Smcpowers CK_BBOOL is_token_obj = FALSE; 254*4219Smcpowers CK_RV rv = CKR_OK; 255*4219Smcpowers ulong_t key_len = 0; 256*4219Smcpowers uint_t attr_count; 257*4219Smcpowers int r; 258*4219Smcpowers 259*4219Smcpowers obj_ngk.ngk_in_count = 0; 260*4219Smcpowers obj_ngk.ngk_out_count = 0; 261*4219Smcpowers 262*4219Smcpowers rv = get_key_len_from_template(pMechanism, pTemplate, ulCount, 263*4219Smcpowers NULL, &key_len); 264*4219Smcpowers if (rv != CRYPTO_SUCCESS) 265*4219Smcpowers goto failed_exit; 266*4219Smcpowers 267*4219Smcpowers if ((key_buf = malloc(key_len)) == NULL) { 268*4219Smcpowers rv = CKR_HOST_MEMORY; 269*4219Smcpowers goto failed_exit; 270*4219Smcpowers } 271*4219Smcpowers 272*4219Smcpowers attr_count = ulCount + 1; 273*4219Smcpowers newTemplate = grow_template(pTemplate, ulCount, attr_count); 274*4219Smcpowers if (newTemplate == NULL) { 275*4219Smcpowers rv = CKR_HOST_MEMORY; 276*4219Smcpowers goto failed_exit; 277*4219Smcpowers } 278*4219Smcpowers 279*4219Smcpowers /* Now add the CKA_VALUE attribute to template */ 280*4219Smcpowers newTemplate[ulCount].type = CKA_VALUE; 281*4219Smcpowers newTemplate[ulCount].pValue = (caddr_t)key_buf; 282*4219Smcpowers newTemplate[ulCount].ulValueLen = key_len; 283*4219Smcpowers 284*4219Smcpowers rv = process_object_attributes(newTemplate, attr_count - 1, 285*4219Smcpowers &obj_ngk.ngk_in_attributes, &is_token_obj); 286*4219Smcpowers if (rv != CKR_OK) { 287*4219Smcpowers goto failed_exit; 288*4219Smcpowers } 289*4219Smcpowers rv = process_object_attributes(&newTemplate[ulCount], 290*4219Smcpowers 1, &obj_ngk.ngk_out_attributes, &is_token_obj); 291*4219Smcpowers if (rv != CKR_OK) { 292*4219Smcpowers goto failed_exit; 293*4219Smcpowers } 294*4219Smcpowers 295*4219Smcpowers /* Cannot create a token object with a READ-ONLY session. */ 296*4219Smcpowers if (is_token_obj && session_p->ses_RO) { 297*4219Smcpowers rv = CKR_SESSION_READ_ONLY; 298*4219Smcpowers goto failed_exit; 299*4219Smcpowers } 300*4219Smcpowers 301*4219Smcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY ioctl */ 302*4219Smcpowers obj_ngk.ngk_session = session_p->k_session; 303*4219Smcpowers obj_ngk.ngk_in_count = attr_count - 1; 304*4219Smcpowers obj_ngk.ngk_out_count = 1; 305*4219Smcpowers obj_ngk.ngk_mechanism.cm_type = k_mech_type; 306*4219Smcpowers obj_ngk.ngk_mechanism.cm_param = pMechanism->pParameter; 307*4219Smcpowers obj_ngk.ngk_mechanism.cm_param_len = pMechanism->ulParameterLen; 308*4219Smcpowers 309*4219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY, 310*4219Smcpowers &obj_ngk)) < 0) { 311*4219Smcpowers if (errno != EINTR) 312*4219Smcpowers break; 313*4219Smcpowers } 314*4219Smcpowers if (r < 0) { 315*4219Smcpowers rv = CKR_FUNCTION_FAILED; 316*4219Smcpowers } else { 317*4219Smcpowers rv = crypto2pkcs11_error_number(obj_ngk.ngk_return_value); 318*4219Smcpowers } 319*4219Smcpowers free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count); 320*4219Smcpowers if (rv != CKR_OK) { 321*4219Smcpowers goto failed_exit; 322*4219Smcpowers } 323*4219Smcpowers 324*4219Smcpowers rv = get_object_attributes(&newTemplate[ulCount], 1, 325*4219Smcpowers obj_ngk.ngk_out_attributes); 326*4219Smcpowers free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count); 327*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 328*4219Smcpowers goto failed_exit; 329*4219Smcpowers } 330*4219Smcpowers 331*4219Smcpowers /* 332*4219Smcpowers * CKA_VALUE_LEN is not stored with the secret key object, 333*4219Smcpowers * so we remove it by shifting attributes down one. 334*4219Smcpowers */ 335*4219Smcpowers (void) remove_one_attribute(newTemplate, CKA_VALUE_LEN, 336*4219Smcpowers attr_count, B_FALSE); 337*4219Smcpowers 338*4219Smcpowers rv = kernel_build_object(newTemplate, attr_count - 1, 339*4219Smcpowers new_objp, session_p, KERNEL_GEN_KEY); 340*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 341*4219Smcpowers goto failed_exit; 342*4219Smcpowers } 343*4219Smcpowers new_objp->is_lib_obj = B_TRUE; 344*4219Smcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 345*4219Smcpowers (void) free(newTemplate); 346*4219Smcpowers bzero(key_buf, key_len); 347*4219Smcpowers (void) free(key_buf); 348*4219Smcpowers return (CKR_OK); 349*4219Smcpowers 350*4219Smcpowers failed_exit: 351*4219Smcpowers free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count); 352*4219Smcpowers free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count); 353*4219Smcpowers if (key_buf != NULL) { 354*4219Smcpowers bzero(key_buf, key_len); 355*4219Smcpowers (void) free(key_buf); 356*4219Smcpowers } 357*4219Smcpowers if (newTemplate != NULL) { 358*4219Smcpowers (void) free(newTemplate); 359*4219Smcpowers } 360*4219Smcpowers return (rv); 361*4219Smcpowers } 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate CK_RV 3640Sstevel@tonic-gate C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 3650Sstevel@tonic-gate CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) 3660Sstevel@tonic-gate { 3670Sstevel@tonic-gate CK_RV rv = CKR_OK; 3680Sstevel@tonic-gate kernel_session_t *session_p; 3690Sstevel@tonic-gate kernel_object_t *new_objp = NULL; 3700Sstevel@tonic-gate kernel_slot_t *pslot; 3710Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 3720Sstevel@tonic-gate CK_BBOOL is_pri_obj; 3730Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE; 3740Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 3750Sstevel@tonic-gate int r; 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate if (!kernel_initialized) 3780Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate /* Obtain the session pointer */ 3810Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 3820Sstevel@tonic-gate if (rv != CKR_OK) 3830Sstevel@tonic-gate return (rv); 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate if ((pMechanism == NULL) || (phKey == NULL)) { 3860Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 3870Sstevel@tonic-gate goto failed_exit; 3880Sstevel@tonic-gate } 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate if ((pTemplate == NULL) && (ulCount != 0)) { 3910Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 3920Sstevel@tonic-gate goto failed_exit; 3930Sstevel@tonic-gate } 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 3960Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 3970Sstevel@tonic-gate if (rv != CKR_OK) { 3980Sstevel@tonic-gate goto failed_exit; 3990Sstevel@tonic-gate } 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate /* Create an object wrapper in the library first */ 4020Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t)); 4030Sstevel@tonic-gate if (new_objp == NULL) { 4040Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 4050Sstevel@tonic-gate goto failed_exit; 4060Sstevel@tonic-gate } 4070Sstevel@tonic-gate 408*4219Smcpowers /* 409*4219Smcpowers * Special Case: if token does not support object creation, 410*4219Smcpowers * but does support key generation by value, then create a session 411*4219Smcpowers * object and initialize with value returned by token. 412*4219Smcpowers */ 413*4219Smcpowers pslot = slot_table[session_p->ses_slotid]; 414*4219Smcpowers if (!pslot->sl_func_list.fl_object_create) { 415*4219Smcpowers rv = key_gen_by_value(pMechanism, pTemplate, ulCount, session_p, 416*4219Smcpowers k_mech_type, new_objp); 417*4219Smcpowers if (rv != CKR_OK) 418*4219Smcpowers goto failed_exit; 419*4219Smcpowers } else { 420*4219Smcpowers crypto_object_generate_key_t obj_gk; 4210Sstevel@tonic-gate 422*4219Smcpowers /* Process the attributes */ 423*4219Smcpowers rv = process_object_attributes(pTemplate, ulCount, 424*4219Smcpowers &obj_gk.gk_attributes, &is_token_obj); 425*4219Smcpowers if (rv != CKR_OK) { 426*4219Smcpowers goto failed_exit; 427*4219Smcpowers } 428*4219Smcpowers /* Cannot create a token object with a READ-ONLY session. */ 429*4219Smcpowers if (is_token_obj && session_p->ses_RO) { 430*4219Smcpowers free_object_attributes(obj_gk.gk_attributes, ulCount); 431*4219Smcpowers rv = CKR_SESSION_READ_ONLY; 432*4219Smcpowers goto failed_exit; 433*4219Smcpowers } 434*4219Smcpowers 435*4219Smcpowers /* Call the CRYPTO_GENERATE_KEY ioctl */ 436*4219Smcpowers obj_gk.gk_session = session_p->k_session; 437*4219Smcpowers obj_gk.gk_count = ulCount; 438*4219Smcpowers obj_gk.gk_mechanism.cm_type = k_mech_type; 439*4219Smcpowers obj_gk.gk_mechanism.cm_param = pMechanism->pParameter; 440*4219Smcpowers obj_gk.gk_mechanism.cm_param_len = pMechanism->ulParameterLen; 4410Sstevel@tonic-gate 442*4219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY, 443*4219Smcpowers &obj_gk)) < 0) { 444*4219Smcpowers if (errno != EINTR) 445*4219Smcpowers break; 446*4219Smcpowers } 447*4219Smcpowers if (r < 0) { 448*4219Smcpowers rv = CKR_FUNCTION_FAILED; 449*4219Smcpowers } else { 450*4219Smcpowers rv = crypto2pkcs11_error_number(obj_gk.gk_return_value); 451*4219Smcpowers } 452*4219Smcpowers 453*4219Smcpowers free_object_attributes(obj_gk.gk_attributes, ulCount); 454*4219Smcpowers 455*4219Smcpowers if (rv != CKR_OK) { 456*4219Smcpowers goto failed_exit; 457*4219Smcpowers } 4580Sstevel@tonic-gate 459*4219Smcpowers /* Get the value of the CKA_PRIVATE attribute. */ 460*4219Smcpowers rv = get_cka_private_value(session_p, obj_gk.gk_handle, 461*4219Smcpowers &is_pri_obj); 462*4219Smcpowers if (rv != CKR_OK) { 463*4219Smcpowers goto failed_exit; 464*4219Smcpowers } 465*4219Smcpowers 466*4219Smcpowers /* 467*4219Smcpowers * Store the kernel object handle in the object wrapper and 468*4219Smcpowers * initialize the library object. 469*4219Smcpowers */ 470*4219Smcpowers new_objp->k_handle = obj_gk.gk_handle; 471*4219Smcpowers new_objp->is_lib_obj = B_FALSE; 472*4219Smcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 473*4219Smcpowers new_objp->extra_attrlistp = NULL; 474*4219Smcpowers 475*4219Smcpowers if (is_pri_obj) 476*4219Smcpowers new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 477*4219Smcpowers else 478*4219Smcpowers new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 479*4219Smcpowers 480*4219Smcpowers if (is_token_obj) 481*4219Smcpowers new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 482*4219Smcpowers else 483*4219Smcpowers new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 4840Sstevel@tonic-gate } 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 4870Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate /* 4900Sstevel@tonic-gate * Add the new object to the slot's token object list if it is a 4910Sstevel@tonic-gate * a token object. Otherwise, add it to the session's object list. 4920Sstevel@tonic-gate */ 4930Sstevel@tonic-gate if (is_token_obj) { 4940Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 4950Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot); 4960Sstevel@tonic-gate } else { 4970Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p); 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp; 5010Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 5020Sstevel@tonic-gate return (rv); 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate failed_exit: 5050Sstevel@tonic-gate if (new_objp != NULL) { 5060Sstevel@tonic-gate (void) free(new_objp); 5070Sstevel@tonic-gate } 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 5100Sstevel@tonic-gate return (rv); 5110Sstevel@tonic-gate } 5120Sstevel@tonic-gate 513*4219Smcpowers CK_RV 514*4219Smcpowers key_gen_rsa_by_value(CK_MECHANISM_PTR pMechanism, 515*4219Smcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 516*4219Smcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 517*4219Smcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type, 518*4219Smcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp) 519*4219Smcpowers { 520*4219Smcpowers crypto_nostore_generate_key_pair_t obj_nkp; 521*4219Smcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL; 522*4219Smcpowers CK_ATTRIBUTE_PTR priTemplate = NULL; 523*4219Smcpowers CK_RV rv = CKR_OK; 524*4219Smcpowers CK_BBOOL is_token_obj1 = FALSE; 525*4219Smcpowers CK_BBOOL is_token_obj2 = FALSE; 526*4219Smcpowers uint_t pub_attr_count, pri_attr_count; 527*4219Smcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0; 528*4219Smcpowers char public_modulus[512]; 529*4219Smcpowers char public_exponent[8]; 530*4219Smcpowers char private_exponent[512]; 531*4219Smcpowers char private_modulus[512]; 532*4219Smcpowers char prime_1[512]; 533*4219Smcpowers char prime_2[512]; 534*4219Smcpowers char exponent_1[512]; 535*4219Smcpowers char exponent_2[512]; 536*4219Smcpowers char coefficient[512]; 537*4219Smcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY; 538*4219Smcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY; 539*4219Smcpowers CK_ULONG key_type; 540*4219Smcpowers CK_ULONG modulus_bytes; 541*4219Smcpowers boolean_t has_class, has_key_type, has_pub_exponent; 542*4219Smcpowers int n, r; 543*4219Smcpowers 544*4219Smcpowers obj_nkp.nkp_in_public_count = 0; 545*4219Smcpowers obj_nkp.nkp_out_public_count = 0; 546*4219Smcpowers obj_nkp.nkp_in_private_count = 0; 547*4219Smcpowers obj_nkp.nkp_out_private_count = 0; 548*4219Smcpowers 549*4219Smcpowers /* modulus bits must be present when generating a RSA key pair */ 550*4219Smcpowers if (!attribute_in_template(CKA_MODULUS_BITS, pPublicKeyTemplate, 551*4219Smcpowers ulPublicKeyAttributeCount)) { 552*4219Smcpowers rv = CKR_TEMPLATE_INCOMPLETE; 553*4219Smcpowers goto failed_exit; 554*4219Smcpowers } 555*4219Smcpowers 556*4219Smcpowers modulus_bytes = get_modulus_bytes(pPublicKeyTemplate, 557*4219Smcpowers ulPublicKeyAttributeCount); 558*4219Smcpowers 559*4219Smcpowers /* 560*4219Smcpowers * Add CKA_MODULUS to the public template. 561*4219Smcpowers * This attribute must not be in the template. 562*4219Smcpowers */ 563*4219Smcpowers if (attribute_in_template(CKA_MODULUS, pPublicKeyTemplate, 564*4219Smcpowers ulPublicKeyAttributeCount)) { 565*4219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT; 566*4219Smcpowers goto failed_exit; 567*4219Smcpowers } 568*4219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate, 569*4219Smcpowers ulPublicKeyAttributeCount); 570*4219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate, 571*4219Smcpowers ulPublicKeyAttributeCount); 572*4219Smcpowers has_pub_exponent = attribute_in_template(CKA_PUBLIC_EXPONENT, 573*4219Smcpowers pPublicKeyTemplate, ulPublicKeyAttributeCount); 574*4219Smcpowers 575*4219Smcpowers pub_attr_count = ulPublicKeyAttributeCount + 1; 576*4219Smcpowers if (!has_class) 577*4219Smcpowers pub_attr_count++; 578*4219Smcpowers if (!has_key_type) 579*4219Smcpowers pub_attr_count++; 580*4219Smcpowers if (!has_pub_exponent) 581*4219Smcpowers pub_attr_count++; 582*4219Smcpowers pubTemplate = grow_template(pPublicKeyTemplate, 583*4219Smcpowers ulPublicKeyAttributeCount, pub_attr_count); 584*4219Smcpowers if (pubTemplate == NULL) { 585*4219Smcpowers rv = CKR_HOST_MEMORY; 586*4219Smcpowers goto failed_exit; 587*4219Smcpowers } 588*4219Smcpowers 589*4219Smcpowers n = ulPublicKeyAttributeCount; 590*4219Smcpowers if (!has_class) { 591*4219Smcpowers pubTemplate[n].type = CKA_CLASS; 592*4219Smcpowers pubTemplate[n].pValue = (caddr_t)&pub_class; 593*4219Smcpowers pubTemplate[n].ulValueLen = sizeof (pub_class); 594*4219Smcpowers n++; 595*4219Smcpowers } 596*4219Smcpowers if (!has_key_type) { 597*4219Smcpowers pubTemplate[n].type = CKA_KEY_TYPE; 598*4219Smcpowers key_type = CKK_RSA; 599*4219Smcpowers pubTemplate[n].pValue = (caddr_t)&key_type; 600*4219Smcpowers pubTemplate[n].ulValueLen = sizeof (key_type); 601*4219Smcpowers n++; 602*4219Smcpowers } 603*4219Smcpowers if (!has_pub_exponent) { 604*4219Smcpowers pubTemplate[n].type = CKA_PUBLIC_EXPONENT; 605*4219Smcpowers pubTemplate[n].pValue = (caddr_t)public_exponent; 606*4219Smcpowers pubTemplate[n].ulValueLen = modulus_bytes; 607*4219Smcpowers n++; 608*4219Smcpowers pub_out_attr_count++; 609*4219Smcpowers } 610*4219Smcpowers pubTemplate[n].type = CKA_MODULUS; 611*4219Smcpowers pubTemplate[n].pValue = (caddr_t)public_modulus; 612*4219Smcpowers pubTemplate[n].ulValueLen = modulus_bytes; 613*4219Smcpowers pub_out_attr_count++; 614*4219Smcpowers 615*4219Smcpowers rv = process_object_attributes(pubTemplate, 616*4219Smcpowers pub_attr_count - pub_out_attr_count, 617*4219Smcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1); 618*4219Smcpowers if (rv != CKR_OK) { 619*4219Smcpowers goto failed_exit; 620*4219Smcpowers } 621*4219Smcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count; 622*4219Smcpowers 623*4219Smcpowers rv = process_object_attributes( 624*4219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 625*4219Smcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes, 626*4219Smcpowers &is_token_obj1); 627*4219Smcpowers if (rv != CKR_OK) { 628*4219Smcpowers goto failed_exit; 629*4219Smcpowers } 630*4219Smcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count; 631*4219Smcpowers 632*4219Smcpowers /* 633*4219Smcpowers * Cannot create a token object with a READ-ONLY 634*4219Smcpowers * session. 635*4219Smcpowers */ 636*4219Smcpowers if (is_token_obj1 && session_p->ses_RO) { 637*4219Smcpowers rv = CKR_SESSION_READ_ONLY; 638*4219Smcpowers goto failed_exit; 639*4219Smcpowers } 640*4219Smcpowers 641*4219Smcpowers /* 642*4219Smcpowers * Add CKA_MODULUS and CKA_PRIVATE_EXPONENT 643*4219Smcpowers * to the private template. These attributes 644*4219Smcpowers * must not be in the template. 645*4219Smcpowers */ 646*4219Smcpowers if (attribute_in_template(CKA_PRIVATE_EXPONENT, 647*4219Smcpowers pPrivateKeyTemplate, ulPrivateKeyAttributeCount) || 648*4219Smcpowers attribute_in_template(CKA_MODULUS, 649*4219Smcpowers pPrivateKeyTemplate, ulPrivateKeyAttributeCount)) { 650*4219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT; 651*4219Smcpowers goto failed_exit; 652*4219Smcpowers } 653*4219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate, 654*4219Smcpowers ulPrivateKeyAttributeCount); 655*4219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate, 656*4219Smcpowers ulPrivateKeyAttributeCount); 657*4219Smcpowers 658*4219Smcpowers pri_attr_count = ulPrivateKeyAttributeCount + 7; 659*4219Smcpowers if (!has_class) 660*4219Smcpowers pri_attr_count++; 661*4219Smcpowers if (!has_key_type) 662*4219Smcpowers pri_attr_count++; 663*4219Smcpowers 664*4219Smcpowers /* allocate space for CKA_PUBLIC_EXPONENT */ 665*4219Smcpowers priTemplate = grow_template(pPrivateKeyTemplate, 666*4219Smcpowers ulPrivateKeyAttributeCount, pri_attr_count + 1); 667*4219Smcpowers if (priTemplate == NULL) { 668*4219Smcpowers rv = CKR_HOST_MEMORY; 669*4219Smcpowers goto failed_exit; 670*4219Smcpowers } 671*4219Smcpowers n = ulPrivateKeyAttributeCount; 672*4219Smcpowers if (!has_class) { 673*4219Smcpowers priTemplate[n].type = CKA_CLASS; 674*4219Smcpowers priTemplate[n].pValue = (caddr_t)&pri_class; 675*4219Smcpowers priTemplate[n].ulValueLen = sizeof (pri_class); 676*4219Smcpowers n++; 677*4219Smcpowers } 678*4219Smcpowers if (!has_key_type) { 679*4219Smcpowers priTemplate[n].type = CKA_KEY_TYPE; 680*4219Smcpowers key_type = CKK_RSA; 681*4219Smcpowers priTemplate[n].pValue = (caddr_t)&key_type; 682*4219Smcpowers priTemplate[n].ulValueLen = sizeof (key_type); 683*4219Smcpowers n++; 684*4219Smcpowers } 685*4219Smcpowers priTemplate[n].type = CKA_MODULUS; 686*4219Smcpowers priTemplate[n].pValue = (caddr_t)private_modulus; 687*4219Smcpowers priTemplate[n].ulValueLen = modulus_bytes; 688*4219Smcpowers pri_out_attr_count++; 689*4219Smcpowers 690*4219Smcpowers n++; 691*4219Smcpowers priTemplate[n].type = CKA_PRIVATE_EXPONENT; 692*4219Smcpowers priTemplate[n].pValue = (caddr_t)private_exponent; 693*4219Smcpowers priTemplate[n].ulValueLen = modulus_bytes; 694*4219Smcpowers pri_out_attr_count++; 695*4219Smcpowers 696*4219Smcpowers n++; 697*4219Smcpowers priTemplate[n].type = CKA_PRIME_1; 698*4219Smcpowers priTemplate[n].pValue = (caddr_t)prime_1; 699*4219Smcpowers priTemplate[n].ulValueLen = modulus_bytes/2; 700*4219Smcpowers pri_out_attr_count++; 701*4219Smcpowers 702*4219Smcpowers n++; 703*4219Smcpowers priTemplate[n].type = CKA_PRIME_2; 704*4219Smcpowers priTemplate[n].pValue = (caddr_t)prime_2; 705*4219Smcpowers priTemplate[n].ulValueLen = modulus_bytes/2; 706*4219Smcpowers pri_out_attr_count++; 707*4219Smcpowers 708*4219Smcpowers n++; 709*4219Smcpowers priTemplate[n].type = CKA_EXPONENT_1; 710*4219Smcpowers priTemplate[n].pValue = (caddr_t)exponent_1; 711*4219Smcpowers priTemplate[n].ulValueLen = modulus_bytes/2; 712*4219Smcpowers pri_out_attr_count++; 713*4219Smcpowers 714*4219Smcpowers n++; 715*4219Smcpowers priTemplate[n].type = CKA_EXPONENT_2; 716*4219Smcpowers priTemplate[n].pValue = (caddr_t)exponent_2; 717*4219Smcpowers priTemplate[n].ulValueLen = modulus_bytes/2; 718*4219Smcpowers pri_out_attr_count++; 719*4219Smcpowers 720*4219Smcpowers n++; 721*4219Smcpowers priTemplate[n].type = CKA_COEFFICIENT; 722*4219Smcpowers priTemplate[n].pValue = (caddr_t)coefficient; 723*4219Smcpowers priTemplate[n].ulValueLen = modulus_bytes/2; 724*4219Smcpowers pri_out_attr_count++; 725*4219Smcpowers 726*4219Smcpowers rv = process_object_attributes(priTemplate, 727*4219Smcpowers pri_attr_count - pri_out_attr_count, 728*4219Smcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2); 729*4219Smcpowers if (rv != CKR_OK) { 730*4219Smcpowers goto failed_exit; 731*4219Smcpowers } 732*4219Smcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count; 733*4219Smcpowers 734*4219Smcpowers rv = process_object_attributes( 735*4219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 736*4219Smcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes, 737*4219Smcpowers &is_token_obj2); 738*4219Smcpowers if (rv != CKR_OK) { 739*4219Smcpowers goto failed_exit; 740*4219Smcpowers } 741*4219Smcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count; 742*4219Smcpowers 743*4219Smcpowers /* 744*4219Smcpowers * The public key and the private key need to contain the same 745*4219Smcpowers * attribute values for CKA_TOKEN. 746*4219Smcpowers */ 747*4219Smcpowers if (is_token_obj1 != is_token_obj2) { 748*4219Smcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID; 749*4219Smcpowers goto failed_exit; 750*4219Smcpowers } 751*4219Smcpowers 752*4219Smcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */ 753*4219Smcpowers obj_nkp.nkp_session = session_p-> k_session; 754*4219Smcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type; 755*4219Smcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter; 756*4219Smcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen; 757*4219Smcpowers 758*4219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR, 759*4219Smcpowers &obj_nkp)) < 0) { 760*4219Smcpowers if (errno != EINTR) 761*4219Smcpowers break; 762*4219Smcpowers } 763*4219Smcpowers if (r < 0) { 764*4219Smcpowers rv = CKR_FUNCTION_FAILED; 765*4219Smcpowers } else { 766*4219Smcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value); 767*4219Smcpowers } 768*4219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 769*4219Smcpowers &obj_nkp.nkp_in_public_count); 770*4219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 771*4219Smcpowers &obj_nkp.nkp_in_private_count); 772*4219Smcpowers 773*4219Smcpowers if (rv != CKR_OK) { 774*4219Smcpowers goto failed_exit; 775*4219Smcpowers } 776*4219Smcpowers 777*4219Smcpowers rv = get_object_attributes( 778*4219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 779*4219Smcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes); 780*4219Smcpowers if (rv == CRYPTO_SUCCESS) { 781*4219Smcpowers rv = get_object_attributes( 782*4219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 783*4219Smcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes); 784*4219Smcpowers } 785*4219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 786*4219Smcpowers &obj_nkp.nkp_out_public_count); 787*4219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 788*4219Smcpowers &obj_nkp.nkp_out_private_count); 789*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 790*4219Smcpowers goto failed_exit; 791*4219Smcpowers } 792*4219Smcpowers 793*4219Smcpowers /* store generated modulus and public exponent */ 794*4219Smcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp, 795*4219Smcpowers session_p, KERNEL_GEN_KEY); 796*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 797*4219Smcpowers goto failed_exit; 798*4219Smcpowers } 799*4219Smcpowers 800*4219Smcpowers /* 801*4219Smcpowers * Copy CKA_PUBLIC_EXPONENT from the public template 802*4219Smcpowers * to the private template. 803*4219Smcpowers */ 804*4219Smcpowers rv = copy_attribute(CKA_PUBLIC_EXPONENT, pubTemplate, 805*4219Smcpowers pub_attr_count, &priTemplate[pri_attr_count]); 806*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 807*4219Smcpowers goto failed_exit; 808*4219Smcpowers } 809*4219Smcpowers 810*4219Smcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 1, new_pri_objp, 811*4219Smcpowers session_p, KERNEL_GEN_KEY); 812*4219Smcpowers (void) free(priTemplate[pri_attr_count].pValue); 813*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 814*4219Smcpowers goto failed_exit; 815*4219Smcpowers } 816*4219Smcpowers (void) free(pubTemplate); 817*4219Smcpowers (void) free(priTemplate); 818*4219Smcpowers 819*4219Smcpowers new_pub_objp->is_lib_obj = B_TRUE; 820*4219Smcpowers new_pri_objp->is_lib_obj = B_TRUE; 821*4219Smcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 822*4219Smcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 823*4219Smcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 824*4219Smcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 825*4219Smcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 826*4219Smcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 827*4219Smcpowers return (CKR_OK); 828*4219Smcpowers 829*4219Smcpowers failed_exit: 830*4219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 831*4219Smcpowers &obj_nkp.nkp_in_public_count); 832*4219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 833*4219Smcpowers &obj_nkp.nkp_out_public_count); 834*4219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 835*4219Smcpowers &obj_nkp.nkp_in_private_count); 836*4219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 837*4219Smcpowers &obj_nkp.nkp_out_private_count); 838*4219Smcpowers if (pubTemplate != NULL) { 839*4219Smcpowers (void) free(pubTemplate); 840*4219Smcpowers } 841*4219Smcpowers if (priTemplate != NULL) { 842*4219Smcpowers (void) free(priTemplate); 843*4219Smcpowers } 844*4219Smcpowers return (rv); 845*4219Smcpowers } 846*4219Smcpowers 847*4219Smcpowers CK_RV 848*4219Smcpowers key_gen_dh_by_value(CK_MECHANISM_PTR pMechanism, 849*4219Smcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 850*4219Smcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 851*4219Smcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type, 852*4219Smcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp) 853*4219Smcpowers { 854*4219Smcpowers crypto_nostore_generate_key_pair_t obj_nkp; 855*4219Smcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL; 856*4219Smcpowers CK_ATTRIBUTE_PTR priTemplate = NULL; 857*4219Smcpowers CK_RV rv = CKR_OK; 858*4219Smcpowers CK_BBOOL is_token_obj1 = FALSE; 859*4219Smcpowers CK_BBOOL is_token_obj2 = FALSE; 860*4219Smcpowers uint_t pub_attr_count, pri_attr_count; 861*4219Smcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0; 862*4219Smcpowers char public_value[256]; 863*4219Smcpowers char private_value[256]; 864*4219Smcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY; 865*4219Smcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY; 866*4219Smcpowers CK_ULONG key_type; 867*4219Smcpowers boolean_t has_class, has_key_type; 868*4219Smcpowers int n, r; 869*4219Smcpowers 870*4219Smcpowers obj_nkp.nkp_in_public_count = 0; 871*4219Smcpowers obj_nkp.nkp_out_public_count = 0; 872*4219Smcpowers obj_nkp.nkp_in_private_count = 0; 873*4219Smcpowers obj_nkp.nkp_out_private_count = 0; 874*4219Smcpowers 875*4219Smcpowers /* 876*4219Smcpowers * Add CKA_VALUE to the public template. 877*4219Smcpowers * This attribute must not be in the template. 878*4219Smcpowers */ 879*4219Smcpowers if (attribute_in_template(CKA_VALUE, pPublicKeyTemplate, 880*4219Smcpowers ulPublicKeyAttributeCount)) { 881*4219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT; 882*4219Smcpowers goto failed_exit; 883*4219Smcpowers } 884*4219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate, 885*4219Smcpowers ulPublicKeyAttributeCount); 886*4219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate, 887*4219Smcpowers ulPublicKeyAttributeCount); 888*4219Smcpowers 889*4219Smcpowers pub_attr_count = ulPublicKeyAttributeCount + 1; 890*4219Smcpowers if (!has_class) 891*4219Smcpowers pub_attr_count++; 892*4219Smcpowers if (!has_key_type) 893*4219Smcpowers pub_attr_count++; 894*4219Smcpowers pubTemplate = grow_template(pPublicKeyTemplate, 895*4219Smcpowers ulPublicKeyAttributeCount, pub_attr_count); 896*4219Smcpowers if (pubTemplate == NULL) { 897*4219Smcpowers rv = CKR_HOST_MEMORY; 898*4219Smcpowers goto failed_exit; 899*4219Smcpowers } 900*4219Smcpowers 901*4219Smcpowers n = ulPublicKeyAttributeCount; 902*4219Smcpowers if (!has_class) { 903*4219Smcpowers pubTemplate[n].type = CKA_CLASS; 904*4219Smcpowers pubTemplate[n].pValue = (caddr_t)&pub_class; 905*4219Smcpowers pubTemplate[n].ulValueLen = sizeof (pub_class); 906*4219Smcpowers n++; 907*4219Smcpowers } 908*4219Smcpowers if (!has_key_type) { 909*4219Smcpowers pubTemplate[n].type = CKA_KEY_TYPE; 910*4219Smcpowers key_type = CKK_DH; 911*4219Smcpowers pubTemplate[n].pValue = (caddr_t)&key_type; 912*4219Smcpowers pubTemplate[n].ulValueLen = sizeof (key_type); 913*4219Smcpowers n++; 914*4219Smcpowers } 915*4219Smcpowers pubTemplate[n].type = CKA_VALUE; 916*4219Smcpowers pubTemplate[n].pValue = (caddr_t)public_value; 917*4219Smcpowers pubTemplate[n].ulValueLen = sizeof (public_value); 918*4219Smcpowers pub_out_attr_count++; 919*4219Smcpowers 920*4219Smcpowers rv = process_object_attributes(pubTemplate, 921*4219Smcpowers pub_attr_count - pub_out_attr_count, 922*4219Smcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1); 923*4219Smcpowers if (rv != CKR_OK) { 924*4219Smcpowers goto failed_exit; 925*4219Smcpowers } 926*4219Smcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count; 927*4219Smcpowers 928*4219Smcpowers rv = process_object_attributes( 929*4219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 930*4219Smcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes, 931*4219Smcpowers &is_token_obj1); 932*4219Smcpowers if (rv != CKR_OK) { 933*4219Smcpowers goto failed_exit; 934*4219Smcpowers } 935*4219Smcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count; 936*4219Smcpowers 937*4219Smcpowers /* 938*4219Smcpowers * Cannot create a token object with a READ-ONLY 939*4219Smcpowers * session. 940*4219Smcpowers */ 941*4219Smcpowers if (is_token_obj1 && session_p->ses_RO) { 942*4219Smcpowers rv = CKR_SESSION_READ_ONLY; 943*4219Smcpowers goto failed_exit; 944*4219Smcpowers } 945*4219Smcpowers 946*4219Smcpowers /* 947*4219Smcpowers * CKA_BASE, CKA_PRIME, and CKA_VALUE must not appear 948*4219Smcpowers * in private template. 949*4219Smcpowers */ 950*4219Smcpowers if (attribute_in_template(CKA_BASE, pPrivateKeyTemplate, 951*4219Smcpowers ulPrivateKeyAttributeCount) || 952*4219Smcpowers attribute_in_template(CKA_PRIME, pPrivateKeyTemplate, 953*4219Smcpowers ulPrivateKeyAttributeCount) || 954*4219Smcpowers attribute_in_template(CKA_VALUE, pPrivateKeyTemplate, 955*4219Smcpowers ulPrivateKeyAttributeCount)) { 956*4219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT; 957*4219Smcpowers goto failed_exit; 958*4219Smcpowers } 959*4219Smcpowers 960*4219Smcpowers if (attribute_in_template(CKA_VALUE, pPrivateKeyTemplate, 961*4219Smcpowers ulPrivateKeyAttributeCount)) { 962*4219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT; 963*4219Smcpowers goto failed_exit; 964*4219Smcpowers } 965*4219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate, 966*4219Smcpowers ulPrivateKeyAttributeCount); 967*4219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate, 968*4219Smcpowers ulPrivateKeyAttributeCount); 969*4219Smcpowers 970*4219Smcpowers pri_attr_count = ulPrivateKeyAttributeCount + 1; 971*4219Smcpowers if (!has_class) 972*4219Smcpowers pri_attr_count++; 973*4219Smcpowers if (!has_key_type) 974*4219Smcpowers pri_attr_count++; 975*4219Smcpowers 976*4219Smcpowers /* allocate space for CKA_BASE and CKA_PRIME */ 977*4219Smcpowers priTemplate = grow_template(pPrivateKeyTemplate, 978*4219Smcpowers ulPrivateKeyAttributeCount, pri_attr_count + 2); 979*4219Smcpowers if (priTemplate == NULL) { 980*4219Smcpowers rv = CKR_HOST_MEMORY; 981*4219Smcpowers goto failed_exit; 982*4219Smcpowers } 983*4219Smcpowers n = ulPrivateKeyAttributeCount; 984*4219Smcpowers if (!has_class) { 985*4219Smcpowers priTemplate[n].type = CKA_CLASS; 986*4219Smcpowers priTemplate[n].pValue = (caddr_t)&pri_class; 987*4219Smcpowers priTemplate[n].ulValueLen = sizeof (pri_class); 988*4219Smcpowers n++; 989*4219Smcpowers } 990*4219Smcpowers if (!has_key_type) { 991*4219Smcpowers priTemplate[n].type = CKA_KEY_TYPE; 992*4219Smcpowers key_type = CKK_DH; 993*4219Smcpowers priTemplate[n].pValue = (caddr_t)&key_type; 994*4219Smcpowers priTemplate[n].ulValueLen = sizeof (key_type); 995*4219Smcpowers n++; 996*4219Smcpowers } 997*4219Smcpowers priTemplate[n].type = CKA_VALUE; 998*4219Smcpowers priTemplate[n].pValue = (caddr_t)private_value; 999*4219Smcpowers priTemplate[n].ulValueLen = sizeof (private_value); 1000*4219Smcpowers pri_out_attr_count++; 1001*4219Smcpowers 1002*4219Smcpowers rv = process_object_attributes(priTemplate, 1003*4219Smcpowers pri_attr_count - pri_out_attr_count, 1004*4219Smcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2); 1005*4219Smcpowers if (rv != CKR_OK) { 1006*4219Smcpowers goto failed_exit; 1007*4219Smcpowers } 1008*4219Smcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count; 1009*4219Smcpowers 1010*4219Smcpowers rv = process_object_attributes( 1011*4219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 1012*4219Smcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes, 1013*4219Smcpowers &is_token_obj2); 1014*4219Smcpowers if (rv != CKR_OK) { 1015*4219Smcpowers goto failed_exit; 1016*4219Smcpowers } 1017*4219Smcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count; 1018*4219Smcpowers 1019*4219Smcpowers /* 1020*4219Smcpowers * The public key and the private key need to contain the same 1021*4219Smcpowers * attribute values for CKA_TOKEN. 1022*4219Smcpowers */ 1023*4219Smcpowers if (is_token_obj1 != is_token_obj2) { 1024*4219Smcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID; 1025*4219Smcpowers goto failed_exit; 1026*4219Smcpowers } 1027*4219Smcpowers 1028*4219Smcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */ 1029*4219Smcpowers obj_nkp.nkp_session = session_p-> k_session; 1030*4219Smcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type; 1031*4219Smcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter; 1032*4219Smcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen; 1033*4219Smcpowers 1034*4219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR, 1035*4219Smcpowers &obj_nkp)) < 0) { 1036*4219Smcpowers if (errno != EINTR) 1037*4219Smcpowers break; 1038*4219Smcpowers } 1039*4219Smcpowers if (r < 0) { 1040*4219Smcpowers rv = CKR_FUNCTION_FAILED; 1041*4219Smcpowers } else { 1042*4219Smcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value); 1043*4219Smcpowers } 1044*4219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 1045*4219Smcpowers &obj_nkp.nkp_in_public_count); 1046*4219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 1047*4219Smcpowers &obj_nkp.nkp_in_private_count); 1048*4219Smcpowers 1049*4219Smcpowers if (rv != CKR_OK) { 1050*4219Smcpowers goto failed_exit; 1051*4219Smcpowers } 1052*4219Smcpowers 1053*4219Smcpowers rv = get_object_attributes( 1054*4219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 1055*4219Smcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes); 1056*4219Smcpowers if (rv == CRYPTO_SUCCESS) { 1057*4219Smcpowers rv = get_object_attributes( 1058*4219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 1059*4219Smcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes); 1060*4219Smcpowers } 1061*4219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 1062*4219Smcpowers &obj_nkp.nkp_out_public_count); 1063*4219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 1064*4219Smcpowers &obj_nkp.nkp_out_private_count); 1065*4219Smcpowers 1066*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 1067*4219Smcpowers goto failed_exit; 1068*4219Smcpowers } 1069*4219Smcpowers 1070*4219Smcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp, 1071*4219Smcpowers session_p, KERNEL_GEN_KEY); 1072*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 1073*4219Smcpowers goto failed_exit; 1074*4219Smcpowers } 1075*4219Smcpowers 1076*4219Smcpowers /* 1077*4219Smcpowers * Copy CKA_BASE and CKA_PRIME from the public template 1078*4219Smcpowers * to the private template. 1079*4219Smcpowers */ 1080*4219Smcpowers rv = copy_attribute(CKA_BASE, pubTemplate, pub_attr_count, 1081*4219Smcpowers &priTemplate[pri_attr_count]); 1082*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 1083*4219Smcpowers goto failed_exit; 1084*4219Smcpowers } 1085*4219Smcpowers rv = copy_attribute(CKA_PRIME, pubTemplate, pub_attr_count, 1086*4219Smcpowers &priTemplate[pri_attr_count + 1]); 1087*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 1088*4219Smcpowers (void) free(priTemplate[pri_attr_count].pValue); 1089*4219Smcpowers goto failed_exit; 1090*4219Smcpowers } 1091*4219Smcpowers 1092*4219Smcpowers /* +2 to account for CKA_BASE and CKA_PRIME */ 1093*4219Smcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 2, 1094*4219Smcpowers new_pri_objp, session_p, KERNEL_GEN_KEY); 1095*4219Smcpowers (void) free(priTemplate[pri_attr_count].pValue); 1096*4219Smcpowers (void) free(priTemplate[pri_attr_count + 1].pValue); 1097*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 1098*4219Smcpowers goto failed_exit; 1099*4219Smcpowers } 1100*4219Smcpowers (void) free(pubTemplate); 1101*4219Smcpowers (void) free(priTemplate); 1102*4219Smcpowers 1103*4219Smcpowers new_pub_objp->is_lib_obj = B_TRUE; 1104*4219Smcpowers new_pri_objp->is_lib_obj = B_TRUE; 1105*4219Smcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1106*4219Smcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1107*4219Smcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 1108*4219Smcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1109*4219Smcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 1110*4219Smcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1111*4219Smcpowers return (CKR_OK); 1112*4219Smcpowers 1113*4219Smcpowers failed_exit: 1114*4219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 1115*4219Smcpowers &obj_nkp.nkp_in_public_count); 1116*4219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 1117*4219Smcpowers &obj_nkp.nkp_out_public_count); 1118*4219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 1119*4219Smcpowers &obj_nkp.nkp_in_private_count); 1120*4219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 1121*4219Smcpowers &obj_nkp.nkp_out_private_count); 1122*4219Smcpowers if (pubTemplate != NULL) { 1123*4219Smcpowers (void) free(pubTemplate); 1124*4219Smcpowers } 1125*4219Smcpowers if (priTemplate != NULL) { 1126*4219Smcpowers (void) free(priTemplate); 1127*4219Smcpowers } 1128*4219Smcpowers return (rv); 1129*4219Smcpowers } 1130*4219Smcpowers 1131*4219Smcpowers CK_RV 1132*4219Smcpowers key_gen_ec_by_value(CK_MECHANISM_PTR pMechanism, 1133*4219Smcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 1134*4219Smcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 1135*4219Smcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type, 1136*4219Smcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp) 1137*4219Smcpowers { 1138*4219Smcpowers crypto_nostore_generate_key_pair_t obj_nkp; 1139*4219Smcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL; 1140*4219Smcpowers CK_ATTRIBUTE_PTR priTemplate = NULL; 1141*4219Smcpowers CK_RV rv = CKR_OK; 1142*4219Smcpowers CK_BBOOL is_token_obj1 = FALSE; 1143*4219Smcpowers CK_BBOOL is_token_obj2 = FALSE; 1144*4219Smcpowers uint_t pub_attr_count, pri_attr_count; 1145*4219Smcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0; 1146*4219Smcpowers char value[32]; 1147*4219Smcpowers char point[128]; 1148*4219Smcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY; 1149*4219Smcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY; 1150*4219Smcpowers CK_ULONG key_type; 1151*4219Smcpowers boolean_t has_class, has_key_type; 1152*4219Smcpowers int n, r; 1153*4219Smcpowers 1154*4219Smcpowers obj_nkp.nkp_in_public_count = 0; 1155*4219Smcpowers obj_nkp.nkp_out_public_count = 0; 1156*4219Smcpowers obj_nkp.nkp_in_private_count = 0; 1157*4219Smcpowers obj_nkp.nkp_out_private_count = 0; 1158*4219Smcpowers 1159*4219Smcpowers /* 1160*4219Smcpowers * Add CKA_EC_POINT to the public template. 1161*4219Smcpowers * This is the generated value Q. This attribute 1162*4219Smcpowers * must not be in the template. 1163*4219Smcpowers */ 1164*4219Smcpowers if (attribute_in_template(CKA_EC_POINT, pPublicKeyTemplate, 1165*4219Smcpowers ulPublicKeyAttributeCount)) { 1166*4219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT; 1167*4219Smcpowers goto failed_exit; 1168*4219Smcpowers } 1169*4219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate, 1170*4219Smcpowers ulPublicKeyAttributeCount); 1171*4219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate, 1172*4219Smcpowers ulPublicKeyAttributeCount); 1173*4219Smcpowers 1174*4219Smcpowers pub_attr_count = ulPublicKeyAttributeCount + 1; 1175*4219Smcpowers if (!has_class) 1176*4219Smcpowers pub_attr_count++; 1177*4219Smcpowers if (!has_key_type) 1178*4219Smcpowers pub_attr_count++; 1179*4219Smcpowers pubTemplate = grow_template(pPublicKeyTemplate, 1180*4219Smcpowers ulPublicKeyAttributeCount, pub_attr_count); 1181*4219Smcpowers if (pubTemplate == NULL) { 1182*4219Smcpowers rv = CKR_HOST_MEMORY; 1183*4219Smcpowers goto failed_exit; 1184*4219Smcpowers } 1185*4219Smcpowers 1186*4219Smcpowers n = ulPublicKeyAttributeCount; 1187*4219Smcpowers if (!has_class) { 1188*4219Smcpowers pubTemplate[n].type = CKA_CLASS; 1189*4219Smcpowers pubTemplate[n].pValue = (caddr_t)&pub_class; 1190*4219Smcpowers pubTemplate[n].ulValueLen = sizeof (pub_class); 1191*4219Smcpowers n++; 1192*4219Smcpowers } 1193*4219Smcpowers if (!has_key_type) { 1194*4219Smcpowers pubTemplate[n].type = CKA_KEY_TYPE; 1195*4219Smcpowers key_type = CKK_EC; 1196*4219Smcpowers pubTemplate[n].pValue = (caddr_t)&key_type; 1197*4219Smcpowers pubTemplate[n].ulValueLen = sizeof (key_type); 1198*4219Smcpowers n++; 1199*4219Smcpowers } 1200*4219Smcpowers pubTemplate[n].type = CKA_EC_POINT; 1201*4219Smcpowers pubTemplate[n].pValue = (caddr_t)point; 1202*4219Smcpowers pubTemplate[n].ulValueLen = sizeof (point); 1203*4219Smcpowers pub_out_attr_count++; 1204*4219Smcpowers 1205*4219Smcpowers rv = process_object_attributes(pubTemplate, 1206*4219Smcpowers pub_attr_count - pub_out_attr_count, 1207*4219Smcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1); 1208*4219Smcpowers if (rv != CKR_OK) { 1209*4219Smcpowers goto failed_exit; 1210*4219Smcpowers } 1211*4219Smcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count; 1212*4219Smcpowers 1213*4219Smcpowers rv = process_object_attributes( 1214*4219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 1215*4219Smcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes, 1216*4219Smcpowers &is_token_obj1); 1217*4219Smcpowers if (rv != CKR_OK) { 1218*4219Smcpowers goto failed_exit; 1219*4219Smcpowers } 1220*4219Smcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count; 1221*4219Smcpowers 1222*4219Smcpowers /* 1223*4219Smcpowers * Cannot create a token object with a READ-ONLY 1224*4219Smcpowers * session. 1225*4219Smcpowers */ 1226*4219Smcpowers if (is_token_obj1 && session_p->ses_RO) { 1227*4219Smcpowers rv = CKR_SESSION_READ_ONLY; 1228*4219Smcpowers goto failed_exit; 1229*4219Smcpowers } 1230*4219Smcpowers 1231*4219Smcpowers /* 1232*4219Smcpowers * CKA_EC_PARAMS and CKA_VALUE must not appear in 1233*4219Smcpowers * private template. 1234*4219Smcpowers */ 1235*4219Smcpowers if (attribute_in_template(CKA_EC_PARAMS, pPrivateKeyTemplate, 1236*4219Smcpowers ulPrivateKeyAttributeCount) || 1237*4219Smcpowers attribute_in_template(CKA_VALUE, pPrivateKeyTemplate, 1238*4219Smcpowers ulPrivateKeyAttributeCount)) { 1239*4219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT; 1240*4219Smcpowers goto failed_exit; 1241*4219Smcpowers } 1242*4219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate, 1243*4219Smcpowers ulPrivateKeyAttributeCount); 1244*4219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate, 1245*4219Smcpowers ulPrivateKeyAttributeCount); 1246*4219Smcpowers 1247*4219Smcpowers pri_attr_count = ulPrivateKeyAttributeCount + 1; 1248*4219Smcpowers if (!has_class) 1249*4219Smcpowers pri_attr_count++; 1250*4219Smcpowers if (!has_key_type) 1251*4219Smcpowers pri_attr_count++; 1252*4219Smcpowers 1253*4219Smcpowers /* allocate space for CKA_EC_PARAMS */ 1254*4219Smcpowers priTemplate = grow_template(pPrivateKeyTemplate, 1255*4219Smcpowers ulPrivateKeyAttributeCount, pri_attr_count + 1); 1256*4219Smcpowers if (priTemplate == NULL) { 1257*4219Smcpowers rv = CKR_HOST_MEMORY; 1258*4219Smcpowers goto failed_exit; 1259*4219Smcpowers } 1260*4219Smcpowers n = ulPrivateKeyAttributeCount; 1261*4219Smcpowers if (!has_class) { 1262*4219Smcpowers priTemplate[n].type = CKA_CLASS; 1263*4219Smcpowers priTemplate[n].pValue = (caddr_t)&pri_class; 1264*4219Smcpowers priTemplate[n].ulValueLen = sizeof (pri_class); 1265*4219Smcpowers n++; 1266*4219Smcpowers } 1267*4219Smcpowers if (!has_key_type) { 1268*4219Smcpowers priTemplate[n].type = CKA_KEY_TYPE; 1269*4219Smcpowers key_type = CKK_EC; 1270*4219Smcpowers priTemplate[n].pValue = (caddr_t)&key_type; 1271*4219Smcpowers priTemplate[n].ulValueLen = sizeof (key_type); 1272*4219Smcpowers n++; 1273*4219Smcpowers } 1274*4219Smcpowers priTemplate[n].type = CKA_VALUE; 1275*4219Smcpowers priTemplate[n].pValue = (caddr_t)value; 1276*4219Smcpowers priTemplate[n].ulValueLen = sizeof (value); 1277*4219Smcpowers pri_out_attr_count++; 1278*4219Smcpowers 1279*4219Smcpowers rv = process_object_attributes(priTemplate, 1280*4219Smcpowers pri_attr_count - pri_out_attr_count, 1281*4219Smcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2); 1282*4219Smcpowers if (rv != CKR_OK) { 1283*4219Smcpowers goto failed_exit; 1284*4219Smcpowers } 1285*4219Smcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count; 1286*4219Smcpowers 1287*4219Smcpowers rv = process_object_attributes( 1288*4219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 1289*4219Smcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes, 1290*4219Smcpowers &is_token_obj2); 1291*4219Smcpowers if (rv != CKR_OK) { 1292*4219Smcpowers goto failed_exit; 1293*4219Smcpowers } 1294*4219Smcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count; 1295*4219Smcpowers 1296*4219Smcpowers /* 1297*4219Smcpowers * The public key and the private key need to contain the same 1298*4219Smcpowers * attribute values for CKA_TOKEN. 1299*4219Smcpowers */ 1300*4219Smcpowers if (is_token_obj1 != is_token_obj2) { 1301*4219Smcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID; 1302*4219Smcpowers goto failed_exit; 1303*4219Smcpowers } 1304*4219Smcpowers 1305*4219Smcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */ 1306*4219Smcpowers obj_nkp.nkp_session = session_p-> k_session; 1307*4219Smcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type; 1308*4219Smcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter; 1309*4219Smcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen; 1310*4219Smcpowers 1311*4219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR, 1312*4219Smcpowers &obj_nkp)) < 0) { 1313*4219Smcpowers if (errno != EINTR) 1314*4219Smcpowers break; 1315*4219Smcpowers } 1316*4219Smcpowers if (r < 0) { 1317*4219Smcpowers rv = CKR_FUNCTION_FAILED; 1318*4219Smcpowers } else { 1319*4219Smcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value); 1320*4219Smcpowers } 1321*4219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 1322*4219Smcpowers &obj_nkp.nkp_in_public_count); 1323*4219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 1324*4219Smcpowers &obj_nkp.nkp_in_private_count); 1325*4219Smcpowers 1326*4219Smcpowers if (rv != CKR_OK) { 1327*4219Smcpowers goto failed_exit; 1328*4219Smcpowers } 1329*4219Smcpowers 1330*4219Smcpowers rv = get_object_attributes( 1331*4219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 1332*4219Smcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes); 1333*4219Smcpowers if (rv == CRYPTO_SUCCESS) { 1334*4219Smcpowers rv = get_object_attributes( 1335*4219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 1336*4219Smcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes); 1337*4219Smcpowers } 1338*4219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 1339*4219Smcpowers &obj_nkp.nkp_out_public_count); 1340*4219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 1341*4219Smcpowers &obj_nkp.nkp_out_private_count); 1342*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 1343*4219Smcpowers goto failed_exit; 1344*4219Smcpowers } 1345*4219Smcpowers 1346*4219Smcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp, 1347*4219Smcpowers session_p, KERNEL_GEN_KEY); 1348*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 1349*4219Smcpowers goto failed_exit; 1350*4219Smcpowers } 1351*4219Smcpowers 1352*4219Smcpowers /* 1353*4219Smcpowers * Copy CKA_EC_PARAMS from the public template to the 1354*4219Smcpowers * private template. 1355*4219Smcpowers */ 1356*4219Smcpowers rv = copy_attribute(CKA_EC_PARAMS, pubTemplate, pub_attr_count, 1357*4219Smcpowers &priTemplate[pri_attr_count]); 1358*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 1359*4219Smcpowers goto failed_exit; 1360*4219Smcpowers } 1361*4219Smcpowers 1362*4219Smcpowers /* +1 to account for CKA_EC_PARAMS */ 1363*4219Smcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 1, 1364*4219Smcpowers new_pri_objp, session_p, KERNEL_GEN_KEY); 1365*4219Smcpowers (void) free(priTemplate[pri_attr_count].pValue); 1366*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 1367*4219Smcpowers goto failed_exit; 1368*4219Smcpowers } 1369*4219Smcpowers (void) free(pubTemplate); 1370*4219Smcpowers (void) free(priTemplate); 1371*4219Smcpowers 1372*4219Smcpowers new_pub_objp->is_lib_obj = B_TRUE; 1373*4219Smcpowers new_pri_objp->is_lib_obj = B_TRUE; 1374*4219Smcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1375*4219Smcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1376*4219Smcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 1377*4219Smcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1378*4219Smcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 1379*4219Smcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1380*4219Smcpowers return (CKR_OK); 1381*4219Smcpowers 1382*4219Smcpowers failed_exit: 1383*4219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 1384*4219Smcpowers &obj_nkp.nkp_in_public_count); 1385*4219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 1386*4219Smcpowers &obj_nkp.nkp_out_public_count); 1387*4219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 1388*4219Smcpowers &obj_nkp.nkp_in_private_count); 1389*4219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 1390*4219Smcpowers &obj_nkp.nkp_out_private_count); 1391*4219Smcpowers if (pubTemplate != NULL) { 1392*4219Smcpowers (void) free(pubTemplate); 1393*4219Smcpowers } 1394*4219Smcpowers if (priTemplate != NULL) { 1395*4219Smcpowers (void) free(priTemplate); 1396*4219Smcpowers } 1397*4219Smcpowers return (rv); 1398*4219Smcpowers } 13990Sstevel@tonic-gate 14000Sstevel@tonic-gate CK_RV 14010Sstevel@tonic-gate C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 14020Sstevel@tonic-gate CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 14030Sstevel@tonic-gate CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 14040Sstevel@tonic-gate CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) 14050Sstevel@tonic-gate { 14060Sstevel@tonic-gate CK_RV rv = CKR_OK; 14070Sstevel@tonic-gate kernel_session_t *session_p; 14080Sstevel@tonic-gate kernel_object_t *new_pub_objp = NULL; 14090Sstevel@tonic-gate kernel_object_t *new_pri_objp = NULL; 14100Sstevel@tonic-gate kernel_slot_t *pslot; 14110Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 14120Sstevel@tonic-gate CK_BBOOL is_pri_obj1; 14130Sstevel@tonic-gate CK_BBOOL is_pri_obj2; 14140Sstevel@tonic-gate CK_BBOOL is_token_obj1 = FALSE; 14150Sstevel@tonic-gate CK_BBOOL is_token_obj2 = FALSE; 14160Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 14170Sstevel@tonic-gate int r; 1418*4219Smcpowers CK_RV (*func)(CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, 1419*4219Smcpowers CK_ATTRIBUTE_PTR, CK_ULONG, kernel_session_t *, crypto_mech_type_t, 1420*4219Smcpowers kernel_object_t *, kernel_object_t *); 14210Sstevel@tonic-gate 14220Sstevel@tonic-gate if (!kernel_initialized) 14230Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 14240Sstevel@tonic-gate 14250Sstevel@tonic-gate /* Obtain the session pointer. */ 14260Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 14270Sstevel@tonic-gate if (rv != CKR_OK) 14280Sstevel@tonic-gate return (rv); 14290Sstevel@tonic-gate 14300Sstevel@tonic-gate if ((pMechanism == NULL) || (phPublicKey == NULL) || 14310Sstevel@tonic-gate (phPrivateKey == NULL)) { 14320Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 14330Sstevel@tonic-gate goto failed_exit; 14340Sstevel@tonic-gate } 14350Sstevel@tonic-gate 14360Sstevel@tonic-gate if ((pPublicKeyTemplate == NULL) && (ulPublicKeyAttributeCount != 0)) { 14370Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 14380Sstevel@tonic-gate goto failed_exit; 14390Sstevel@tonic-gate } 14400Sstevel@tonic-gate 14410Sstevel@tonic-gate if ((pPrivateKeyTemplate == NULL) && 14420Sstevel@tonic-gate (ulPrivateKeyAttributeCount != 0)) { 14430Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 14440Sstevel@tonic-gate goto failed_exit; 14450Sstevel@tonic-gate } 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 14480Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 14490Sstevel@tonic-gate if (rv != CKR_OK) { 14500Sstevel@tonic-gate goto failed_exit; 14510Sstevel@tonic-gate } 14520Sstevel@tonic-gate 14530Sstevel@tonic-gate /* Create an object wrapper for the public key */ 14540Sstevel@tonic-gate new_pub_objp = calloc(1, sizeof (kernel_object_t)); 14550Sstevel@tonic-gate if (new_pub_objp == NULL) { 14560Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 14570Sstevel@tonic-gate goto failed_exit; 14580Sstevel@tonic-gate } 14590Sstevel@tonic-gate 14600Sstevel@tonic-gate /* Create an object wrapper for the private key. */ 14610Sstevel@tonic-gate new_pri_objp = calloc(1, sizeof (kernel_object_t)); 14620Sstevel@tonic-gate if (new_pri_objp == NULL) { 14630Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 14640Sstevel@tonic-gate goto failed_exit; 14650Sstevel@tonic-gate } 14660Sstevel@tonic-gate 1467*4219Smcpowers /* 1468*4219Smcpowers * Special Case: if token does not support object creation, 1469*4219Smcpowers * but does support key generation by value, then create a session 1470*4219Smcpowers * object and initialize with values returned by token. 1471*4219Smcpowers */ 1472*4219Smcpowers pslot = slot_table[session_p->ses_slotid]; 1473*4219Smcpowers if (!pslot->sl_func_list.fl_object_create) { 1474*4219Smcpowers switch (pMechanism->mechanism) { 1475*4219Smcpowers case CKM_RSA_PKCS_KEY_PAIR_GEN: 1476*4219Smcpowers func = key_gen_rsa_by_value; 1477*4219Smcpowers break; 1478*4219Smcpowers 1479*4219Smcpowers case CKM_DH_PKCS_KEY_PAIR_GEN: 1480*4219Smcpowers func = key_gen_dh_by_value; 1481*4219Smcpowers break; 1482*4219Smcpowers 1483*4219Smcpowers case CKM_EC_KEY_PAIR_GEN: 1484*4219Smcpowers func = key_gen_ec_by_value; 1485*4219Smcpowers break; 14860Sstevel@tonic-gate 1487*4219Smcpowers default: 1488*4219Smcpowers rv = CKR_MECHANISM_INVALID; 1489*4219Smcpowers goto failed_exit; 1490*4219Smcpowers } 1491*4219Smcpowers rv = (*func)(pMechanism, pPublicKeyTemplate, 1492*4219Smcpowers ulPublicKeyAttributeCount, pPrivateKeyTemplate, 1493*4219Smcpowers ulPrivateKeyAttributeCount, session_p, k_mech_type, 1494*4219Smcpowers new_pub_objp, new_pri_objp); 1495*4219Smcpowers if (rv != CKR_OK) 1496*4219Smcpowers goto failed_exit; 1497*4219Smcpowers } else { 1498*4219Smcpowers crypto_object_generate_key_pair_t obj_kp; 1499*4219Smcpowers 1500*4219Smcpowers /* Process the public key attributes. */ 1501*4219Smcpowers rv = process_object_attributes(pPublicKeyTemplate, 1502*4219Smcpowers ulPublicKeyAttributeCount, &obj_kp.kp_public_attributes, 1503*4219Smcpowers &is_token_obj1); 1504*4219Smcpowers if (rv != CKR_OK) { 1505*4219Smcpowers goto failed_exit; 1506*4219Smcpowers } 15070Sstevel@tonic-gate 1508*4219Smcpowers /* Cannot create a token object with a READ-ONLY session. */ 1509*4219Smcpowers if (is_token_obj1 && session_p->ses_RO) { 1510*4219Smcpowers free_object_attributes(obj_kp.kp_public_attributes, 1511*4219Smcpowers ulPublicKeyAttributeCount); 1512*4219Smcpowers rv = CKR_SESSION_READ_ONLY; 1513*4219Smcpowers goto failed_exit; 1514*4219Smcpowers } 1515*4219Smcpowers 1516*4219Smcpowers /* Process the private key attributes. */ 1517*4219Smcpowers rv = process_object_attributes(pPrivateKeyTemplate, 1518*4219Smcpowers ulPrivateKeyAttributeCount, &obj_kp.kp_private_attributes, 1519*4219Smcpowers &is_token_obj2); 1520*4219Smcpowers if (rv != CKR_OK) { 1521*4219Smcpowers free_object_attributes(obj_kp.kp_public_attributes, 1522*4219Smcpowers ulPublicKeyAttributeCount); 1523*4219Smcpowers goto failed_exit; 1524*4219Smcpowers } 15250Sstevel@tonic-gate 1526*4219Smcpowers /* 1527*4219Smcpowers * The public key and the private key need to contain the same 1528*4219Smcpowers * attribute values for CKA_TOKEN. 1529*4219Smcpowers */ 1530*4219Smcpowers if (is_token_obj1 != is_token_obj2) { 1531*4219Smcpowers free_object_attributes(obj_kp.kp_public_attributes, 1532*4219Smcpowers ulPublicKeyAttributeCount); 1533*4219Smcpowers free_object_attributes(obj_kp.kp_private_attributes, 1534*4219Smcpowers ulPrivateKeyAttributeCount); 1535*4219Smcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID; 1536*4219Smcpowers goto failed_exit; 1537*4219Smcpowers } 1538*4219Smcpowers 1539*4219Smcpowers /* Call the CRYPTO_GENERATE_KEY_PAIR ioctl. */ 1540*4219Smcpowers obj_kp.kp_session = session_p-> k_session; 1541*4219Smcpowers obj_kp.kp_mechanism.cm_type = k_mech_type; 1542*4219Smcpowers obj_kp.kp_mechanism.cm_param = pMechanism->pParameter; 1543*4219Smcpowers obj_kp.kp_mechanism.cm_param_len = pMechanism->ulParameterLen; 1544*4219Smcpowers obj_kp.kp_public_count = ulPublicKeyAttributeCount; 1545*4219Smcpowers obj_kp.kp_private_count = ulPrivateKeyAttributeCount; 1546*4219Smcpowers 1547*4219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY_PAIR, 1548*4219Smcpowers &obj_kp)) < 0) { 1549*4219Smcpowers if (errno != EINTR) 1550*4219Smcpowers break; 1551*4219Smcpowers } 1552*4219Smcpowers if (r < 0) { 1553*4219Smcpowers rv = CKR_FUNCTION_FAILED; 1554*4219Smcpowers } else { 1555*4219Smcpowers rv = crypto2pkcs11_error_number(obj_kp.kp_return_value); 1556*4219Smcpowers } 15570Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes, 15580Sstevel@tonic-gate ulPublicKeyAttributeCount); 15590Sstevel@tonic-gate free_object_attributes(obj_kp.kp_private_attributes, 15600Sstevel@tonic-gate ulPrivateKeyAttributeCount); 1561*4219Smcpowers 1562*4219Smcpowers if (rv != CKR_OK) 1563*4219Smcpowers goto failed_exit; 1564*4219Smcpowers 1565*4219Smcpowers /* Get the CKA_PRIVATE value for the key pair. */ 1566*4219Smcpowers rv = get_cka_private_value(session_p, obj_kp.kp_public_handle, 1567*4219Smcpowers &is_pri_obj1); 1568*4219Smcpowers if (rv != CKR_OK) { 1569*4219Smcpowers goto failed_exit; 1570*4219Smcpowers } 15710Sstevel@tonic-gate 1572*4219Smcpowers rv = get_cka_private_value(session_p, obj_kp.kp_private_handle, 1573*4219Smcpowers &is_pri_obj2); 1574*4219Smcpowers if (rv != CKR_OK) { 1575*4219Smcpowers goto failed_exit; 1576*4219Smcpowers } 1577*4219Smcpowers 1578*4219Smcpowers /* 1579*4219Smcpowers * Store the kernel public key handle into the public key 1580*4219Smcpowers * object and finish the public key object initialization. 1581*4219Smcpowers */ 1582*4219Smcpowers new_pub_objp->is_lib_obj = B_FALSE; 1583*4219Smcpowers new_pub_objp->k_handle = obj_kp.kp_public_handle; 1584*4219Smcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1585*4219Smcpowers new_pub_objp->extra_attrlistp = NULL; 15860Sstevel@tonic-gate 1587*4219Smcpowers if (is_pri_obj1) 1588*4219Smcpowers new_pub_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 1589*4219Smcpowers else 1590*4219Smcpowers new_pub_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 15910Sstevel@tonic-gate 1592*4219Smcpowers if (is_token_obj1) 1593*4219Smcpowers new_pub_objp->bool_attr_mask |= TOKEN_BOOL_ON; 1594*4219Smcpowers else 1595*4219Smcpowers new_pub_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 1596*4219Smcpowers 1597*4219Smcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 1598*4219Smcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 15990Sstevel@tonic-gate 1600*4219Smcpowers /* 1601*4219Smcpowers * Store the kernel private key handle into the private key 1602*4219Smcpowers * object and finish the private key object initialization. 1603*4219Smcpowers */ 1604*4219Smcpowers new_pri_objp->is_lib_obj = B_FALSE; 1605*4219Smcpowers new_pri_objp->k_handle = obj_kp.kp_private_handle; 1606*4219Smcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1607*4219Smcpowers new_pri_objp->extra_attrlistp = NULL; 16080Sstevel@tonic-gate 1609*4219Smcpowers if (is_pri_obj2) 1610*4219Smcpowers new_pri_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 1611*4219Smcpowers else 1612*4219Smcpowers new_pri_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 16130Sstevel@tonic-gate 1614*4219Smcpowers if (is_token_obj2) 1615*4219Smcpowers new_pri_objp->bool_attr_mask |= TOKEN_BOOL_ON; 1616*4219Smcpowers else 1617*4219Smcpowers new_pri_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 1618*4219Smcpowers 16190Sstevel@tonic-gate } 16200Sstevel@tonic-gate (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 16210Sstevel@tonic-gate new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 16220Sstevel@tonic-gate 16230Sstevel@tonic-gate /* 16240Sstevel@tonic-gate * Add the new pub/pri objects to the slot's token list if they are 16250Sstevel@tonic-gate * token objects. Otherwise, add them to the session's object list. 16260Sstevel@tonic-gate */ 16270Sstevel@tonic-gate if (is_token_obj1) { /* is_token_obj1 == is_token_obj2 */ 16280Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 16290Sstevel@tonic-gate kernel_add_token_object_to_slot(new_pub_objp, pslot); 16300Sstevel@tonic-gate kernel_add_token_object_to_slot(new_pri_objp, pslot); 16310Sstevel@tonic-gate } else { 16320Sstevel@tonic-gate kernel_add_object_to_session(new_pub_objp, session_p); 16330Sstevel@tonic-gate kernel_add_object_to_session(new_pri_objp, session_p); 16340Sstevel@tonic-gate } 16350Sstevel@tonic-gate 16360Sstevel@tonic-gate *phPublicKey = (CK_OBJECT_HANDLE)new_pub_objp; 16370Sstevel@tonic-gate *phPrivateKey = (CK_OBJECT_HANDLE)new_pri_objp; 16380Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 16390Sstevel@tonic-gate return (rv); 16400Sstevel@tonic-gate 16410Sstevel@tonic-gate failed_exit: 16420Sstevel@tonic-gate if (new_pub_objp != NULL) { 16430Sstevel@tonic-gate (void) free(new_pub_objp); 16440Sstevel@tonic-gate } 16450Sstevel@tonic-gate if (new_pri_objp != NULL) { 16460Sstevel@tonic-gate (void) free(new_pri_objp); 16470Sstevel@tonic-gate } 16480Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 16490Sstevel@tonic-gate return (rv); 16500Sstevel@tonic-gate } 16510Sstevel@tonic-gate 16520Sstevel@tonic-gate 16530Sstevel@tonic-gate CK_RV 16540Sstevel@tonic-gate C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 16550Sstevel@tonic-gate CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, 16560Sstevel@tonic-gate CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) 16570Sstevel@tonic-gate { 16580Sstevel@tonic-gate CK_RV rv = CKR_OK; 16590Sstevel@tonic-gate kernel_session_t *session_p; 16600Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 16610Sstevel@tonic-gate kernel_object_t *wrappingkey_p; 16620Sstevel@tonic-gate kernel_object_t *key_p; 16630Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 16640Sstevel@tonic-gate crypto_object_wrap_key_t obj_wrapkey; 16650Sstevel@tonic-gate int r; 16660Sstevel@tonic-gate 16670Sstevel@tonic-gate if (!kernel_initialized) 16680Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 16690Sstevel@tonic-gate 16700Sstevel@tonic-gate if (pulWrappedKeyLen == NULL || pMechanism == NULL) { 16710Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 16720Sstevel@tonic-gate } 16730Sstevel@tonic-gate 16740Sstevel@tonic-gate /* 16750Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session 16760Sstevel@tonic-gate * reference count. 16770Sstevel@tonic-gate */ 16780Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 16790Sstevel@tonic-gate if (rv != CKR_OK) 16800Sstevel@tonic-gate return (rv); 16810Sstevel@tonic-gate 16820Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 16830Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 16840Sstevel@tonic-gate if (rv != CKR_OK) { 16850Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 16860Sstevel@tonic-gate return (rv); 16870Sstevel@tonic-gate } 16880Sstevel@tonic-gate 16890Sstevel@tonic-gate /* Obtain the wrapping key object pointer. */ 16900Sstevel@tonic-gate HANDLE2OBJECT(hWrappingKey, wrappingkey_p, rv); 16910Sstevel@tonic-gate if (rv != CKR_OK) { 16920Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 16930Sstevel@tonic-gate return (rv); 16940Sstevel@tonic-gate } 16950Sstevel@tonic-gate 16960Sstevel@tonic-gate /* Obtain the to_be_wrapped key object pointer. */ 16970Sstevel@tonic-gate HANDLE2OBJECT(hKey, key_p, rv); 16980Sstevel@tonic-gate if (rv != CKR_OK) { 1699214Smcpowers OBJ_REFRELE(wrappingkey_p); 17000Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 17010Sstevel@tonic-gate return (rv); 17020Sstevel@tonic-gate } 17030Sstevel@tonic-gate 17040Sstevel@tonic-gate /* Make the CRYPTO_OBJECT_WRAP_KEY ioctl call. */ 17050Sstevel@tonic-gate obj_wrapkey.wk_session = session_p->k_session; 17060Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_type = k_mech_type; 17070Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_param = pMechanism->pParameter; 17080Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_param_len = pMechanism->ulParameterLen; 17090Sstevel@tonic-gate obj_wrapkey.wk_wrapping_key.ck_format = CRYPTO_KEY_REFERENCE; 17100Sstevel@tonic-gate obj_wrapkey.wk_wrapping_key.ck_obj_id = wrappingkey_p->k_handle; 17110Sstevel@tonic-gate obj_wrapkey.wk_object_handle = key_p->k_handle; 17120Sstevel@tonic-gate obj_wrapkey.wk_wrapped_key_len = *pulWrappedKeyLen; 17130Sstevel@tonic-gate obj_wrapkey.wk_wrapped_key = (char *)pWrappedKey; 17140Sstevel@tonic-gate 17150Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_WRAP_KEY, &obj_wrapkey)) < 0) { 17160Sstevel@tonic-gate if (errno != EINTR) 17170Sstevel@tonic-gate break; 17180Sstevel@tonic-gate } 17190Sstevel@tonic-gate if (r < 0) { 17200Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 17210Sstevel@tonic-gate } else { 17220Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_wrapkey.wk_return_value); 17230Sstevel@tonic-gate } 17240Sstevel@tonic-gate 17250Sstevel@tonic-gate /* 17260Sstevel@tonic-gate * Besides rv == CKR_OK, we will set the value of pulWrappedKeyLen 17270Sstevel@tonic-gate * when the applciation-supplied wrapped key buffer is too small. 17280Sstevel@tonic-gate * The situation that the application only asks for the length of 17290Sstevel@tonic-gate * the wrapped key is covered in rv == CKR_OK. 17300Sstevel@tonic-gate */ 17310Sstevel@tonic-gate if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) { 17320Sstevel@tonic-gate *pulWrappedKeyLen = obj_wrapkey.wk_wrapped_key_len; 17330Sstevel@tonic-gate } 17340Sstevel@tonic-gate 1735214Smcpowers OBJ_REFRELE(key_p); 1736214Smcpowers OBJ_REFRELE(wrappingkey_p); 17370Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 17380Sstevel@tonic-gate return (rv); 17390Sstevel@tonic-gate } 17400Sstevel@tonic-gate 17410Sstevel@tonic-gate 17420Sstevel@tonic-gate CK_RV 17430Sstevel@tonic-gate C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 17440Sstevel@tonic-gate CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, 17450Sstevel@tonic-gate CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, 17460Sstevel@tonic-gate CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) 17470Sstevel@tonic-gate { 17480Sstevel@tonic-gate CK_RV rv = CKR_OK; 17490Sstevel@tonic-gate kernel_session_t *session_p; 17500Sstevel@tonic-gate kernel_object_t *unwrappingkey_p; 17510Sstevel@tonic-gate kernel_object_t *new_objp = NULL; 17520Sstevel@tonic-gate kernel_slot_t *pslot; 17530Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 17540Sstevel@tonic-gate CK_BBOOL is_pri_obj; 17550Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE; 17560Sstevel@tonic-gate CK_MECHANISM_INFO info; 17570Sstevel@tonic-gate uint32_t k_mi_flags; 17580Sstevel@tonic-gate CK_BYTE *clear_key_val = NULL; 17590Sstevel@tonic-gate CK_ULONG ulDataLen; 17600Sstevel@tonic-gate CK_ATTRIBUTE_PTR newTemplate = NULL; 17610Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 17620Sstevel@tonic-gate crypto_object_unwrap_key_t obj_unwrapkey; 17630Sstevel@tonic-gate int r; 17640Sstevel@tonic-gate 17650Sstevel@tonic-gate if (!kernel_initialized) 17660Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 17670Sstevel@tonic-gate 17680Sstevel@tonic-gate if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL) { 17690Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 17700Sstevel@tonic-gate } 17710Sstevel@tonic-gate 17720Sstevel@tonic-gate if ((pTemplate == NULL) && (ulAttributeCount != 0)) { 17730Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 17740Sstevel@tonic-gate } 17750Sstevel@tonic-gate 17760Sstevel@tonic-gate /* Obtain the session pointer. */ 17770Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 17780Sstevel@tonic-gate if (rv != CKR_OK) 17790Sstevel@tonic-gate return (rv); 17800Sstevel@tonic-gate 17810Sstevel@tonic-gate /* Obtain the wrapping key object pointer. */ 17820Sstevel@tonic-gate HANDLE2OBJECT(hUnwrappingKey, unwrappingkey_p, rv); 17830Sstevel@tonic-gate if (rv != CKR_OK) { 1784214Smcpowers REFRELE(session_p, ses_lock_held); 1785214Smcpowers return (rv); 17860Sstevel@tonic-gate } 17870Sstevel@tonic-gate 17880Sstevel@tonic-gate /* 17890Sstevel@tonic-gate * If the HW provider doesn't support C_UnwrapKey, we will try 17900Sstevel@tonic-gate * to emulate it in the library. 17910Sstevel@tonic-gate */ 17920Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 1793*4219Smcpowers if ((!pslot->sl_func_list.fl_object_create) && 1794*4219Smcpowers (!pslot->sl_func_list.fl_key_unwrap)) { 17950Sstevel@tonic-gate rv = get_mechanism_info(pslot, pMechanism->mechanism, &info, 17960Sstevel@tonic-gate &k_mi_flags); 17970Sstevel@tonic-gate if (rv != CKR_OK) { 17980Sstevel@tonic-gate goto failed_exit; 17990Sstevel@tonic-gate } 18000Sstevel@tonic-gate 18010Sstevel@tonic-gate /* 18020Sstevel@tonic-gate * If the mechanism flag doesn't have CKF_UNWRAP, and it's 18030Sstevel@tonic-gate * an unwrapping of a secret key object, then help this 18040Sstevel@tonic-gate * out with a decryption followed by an object creation. 18050Sstevel@tonic-gate */ 18060Sstevel@tonic-gate if (!(k_mi_flags & CRYPTO_FG_UNWRAP) && 18070Sstevel@tonic-gate (k_mi_flags & CRYPTO_FG_DECRYPT) && 18080Sstevel@tonic-gate (is_secret_key_template(pTemplate, ulAttributeCount))) { 18090Sstevel@tonic-gate 18100Sstevel@tonic-gate /* First allocate space for the recovered key value */ 18110Sstevel@tonic-gate clear_key_val = malloc(ulWrappedKeyLen); 18120Sstevel@tonic-gate if (clear_key_val == NULL) { 18130Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 18140Sstevel@tonic-gate goto failed_exit; 18150Sstevel@tonic-gate } 18160Sstevel@tonic-gate 18170Sstevel@tonic-gate rv = kernel_decrypt_init(session_p, unwrappingkey_p, 18180Sstevel@tonic-gate pMechanism); 18190Sstevel@tonic-gate if (rv != CKR_OK) { 18200Sstevel@tonic-gate goto failed_exit; 18210Sstevel@tonic-gate } 18220Sstevel@tonic-gate 18230Sstevel@tonic-gate ulDataLen = ulWrappedKeyLen; 18240Sstevel@tonic-gate rv = kernel_decrypt(session_p, pWrappedKey, 18250Sstevel@tonic-gate ulWrappedKeyLen, clear_key_val, &ulDataLen); 18260Sstevel@tonic-gate if (rv != CKR_OK) { 18270Sstevel@tonic-gate goto failed_exit; 18280Sstevel@tonic-gate } 18290Sstevel@tonic-gate 1830*4219Smcpowers newTemplate = grow_template(pTemplate, ulAttributeCount, 1831*4219Smcpowers ulAttributeCount + 1); 18320Sstevel@tonic-gate if (newTemplate == NULL) { 18330Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 18340Sstevel@tonic-gate goto failed_exit; 18350Sstevel@tonic-gate } 1836*4219Smcpowers /* Now add the CKA_VALUE attribute to template */ 18370Sstevel@tonic-gate newTemplate[ulAttributeCount].type = CKA_VALUE; 18380Sstevel@tonic-gate newTemplate[ulAttributeCount].pValue = clear_key_val; 18390Sstevel@tonic-gate newTemplate[ulAttributeCount].ulValueLen = ulDataLen; 18400Sstevel@tonic-gate 18410Sstevel@tonic-gate /* Finally create the key, based on the new template */ 18420Sstevel@tonic-gate rv = kernel_add_object(newTemplate, 18430Sstevel@tonic-gate ulAttributeCount + 1, phKey, session_p); 18440Sstevel@tonic-gate (void) free(clear_key_val); 18450Sstevel@tonic-gate (void) free(newTemplate); 1846214Smcpowers OBJ_REFRELE(unwrappingkey_p); 18470Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 18480Sstevel@tonic-gate return (rv); 18490Sstevel@tonic-gate } else { 18500Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 18510Sstevel@tonic-gate goto failed_exit; 18520Sstevel@tonic-gate } 18530Sstevel@tonic-gate } 18540Sstevel@tonic-gate 18550Sstevel@tonic-gate /* 18560Sstevel@tonic-gate * If we come here, the HW provider must have registered the unwrapkey 18570Sstevel@tonic-gate * entry. Therefore, the unwrap key will be performed in the HW 18580Sstevel@tonic-gate * provider. 18590Sstevel@tonic-gate */ 18600Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 18610Sstevel@tonic-gate if (rv != CKR_OK) { 18620Sstevel@tonic-gate goto failed_exit; 18630Sstevel@tonic-gate } 18640Sstevel@tonic-gate 18650Sstevel@tonic-gate /* Create an object wrapper for the new key in the library first */ 18660Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t)); 18670Sstevel@tonic-gate if (new_objp == NULL) { 18680Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 18690Sstevel@tonic-gate goto failed_exit; 18700Sstevel@tonic-gate } 18710Sstevel@tonic-gate 18720Sstevel@tonic-gate /* Process the attributes */ 18730Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulAttributeCount, 18740Sstevel@tonic-gate &obj_unwrapkey.uk_attributes, &is_token_obj); 18750Sstevel@tonic-gate if (rv != CKR_OK) { 18760Sstevel@tonic-gate goto failed_exit; 18770Sstevel@tonic-gate } 18780Sstevel@tonic-gate 18790Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */ 18800Sstevel@tonic-gate if (is_token_obj && session_p->ses_RO) { 18810Sstevel@tonic-gate free_object_attributes(obj_unwrapkey.uk_attributes, 18820Sstevel@tonic-gate ulAttributeCount); 18830Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY; 18840Sstevel@tonic-gate goto failed_exit; 18850Sstevel@tonic-gate } 18860Sstevel@tonic-gate 18870Sstevel@tonic-gate /* Make the CRYPTO_UNWRAP_KEY ioctl call. */ 18880Sstevel@tonic-gate obj_unwrapkey.uk_session = session_p->k_session; 18890Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_type = k_mech_type; 18900Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_param = pMechanism->pParameter; 18910Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_param_len = pMechanism->ulParameterLen; 18920Sstevel@tonic-gate obj_unwrapkey.uk_unwrapping_key.ck_format = CRYPTO_KEY_REFERENCE; 18930Sstevel@tonic-gate obj_unwrapkey.uk_unwrapping_key.ck_obj_id = unwrappingkey_p->k_handle; 18940Sstevel@tonic-gate obj_unwrapkey.uk_wrapped_key = (char *)pWrappedKey; 18950Sstevel@tonic-gate obj_unwrapkey.uk_wrapped_key_len = ulWrappedKeyLen; 18960Sstevel@tonic-gate obj_unwrapkey.uk_count = ulAttributeCount; 18970Sstevel@tonic-gate 18980Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_UNWRAP_KEY, &obj_unwrapkey)) < 0) { 18990Sstevel@tonic-gate if (errno != EINTR) 19000Sstevel@tonic-gate break; 19010Sstevel@tonic-gate } 19020Sstevel@tonic-gate if (r < 0) { 19030Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 19040Sstevel@tonic-gate } else { 19050Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_unwrapkey.uk_return_value); 19060Sstevel@tonic-gate } 19070Sstevel@tonic-gate 19080Sstevel@tonic-gate free_object_attributes(obj_unwrapkey.uk_attributes, ulAttributeCount); 19090Sstevel@tonic-gate if (rv != CKR_OK) { 19100Sstevel@tonic-gate goto failed_exit; 19110Sstevel@tonic-gate } 19120Sstevel@tonic-gate 19130Sstevel@tonic-gate /* Get the CKA_PRIVATE value for the unwrapped key. */ 19140Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_unwrapkey.uk_object_handle, 19150Sstevel@tonic-gate &is_pri_obj); 19160Sstevel@tonic-gate if (rv != CKR_OK) { 19170Sstevel@tonic-gate goto failed_exit; 19180Sstevel@tonic-gate } 19190Sstevel@tonic-gate 19200Sstevel@tonic-gate /* 19210Sstevel@tonic-gate * Store the kernel object handle in the new key object wrapper and 19220Sstevel@tonic-gate * initialize it. 19230Sstevel@tonic-gate */ 19240Sstevel@tonic-gate new_objp->k_handle = obj_unwrapkey.uk_object_handle; 19250Sstevel@tonic-gate new_objp->is_lib_obj = B_FALSE; 19260Sstevel@tonic-gate new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 19270Sstevel@tonic-gate new_objp->extra_attrlistp = NULL; 19280Sstevel@tonic-gate 19290Sstevel@tonic-gate if (is_pri_obj) 19300Sstevel@tonic-gate new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 19310Sstevel@tonic-gate else 19320Sstevel@tonic-gate new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 19330Sstevel@tonic-gate 19340Sstevel@tonic-gate if (is_token_obj) 19350Sstevel@tonic-gate new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 19360Sstevel@tonic-gate else 19370Sstevel@tonic-gate new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 19380Sstevel@tonic-gate 19390Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 19400Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 19410Sstevel@tonic-gate 19420Sstevel@tonic-gate /* 19430Sstevel@tonic-gate * Add the new object to the slot's token object list if it is a 19440Sstevel@tonic-gate * a token object. Otherwise, add it to the session's object list. 19450Sstevel@tonic-gate */ 19460Sstevel@tonic-gate if (is_token_obj) { 19470Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 19480Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot); 19490Sstevel@tonic-gate } else { 19500Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p); 19510Sstevel@tonic-gate } 19520Sstevel@tonic-gate 19530Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp; 1954214Smcpowers OBJ_REFRELE(unwrappingkey_p); 19550Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 19560Sstevel@tonic-gate return (rv); 19570Sstevel@tonic-gate 19580Sstevel@tonic-gate failed_exit: 1959214Smcpowers OBJ_REFRELE(unwrappingkey_p); 19600Sstevel@tonic-gate if (new_objp != NULL) 19610Sstevel@tonic-gate (void) free(new_objp); 19620Sstevel@tonic-gate 19630Sstevel@tonic-gate if (clear_key_val != NULL) 19640Sstevel@tonic-gate (void) free(clear_key_val); 19650Sstevel@tonic-gate 19660Sstevel@tonic-gate if (newTemplate != NULL) 19670Sstevel@tonic-gate (void) free(newTemplate); 19680Sstevel@tonic-gate 19690Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 19700Sstevel@tonic-gate return (rv); 19710Sstevel@tonic-gate } 19720Sstevel@tonic-gate 1973*4219Smcpowers /* 1974*4219Smcpowers * Get sufficient attributes from a base key to pass by value in a 1975*4219Smcpowers * crypto_key structure. Storage for attributes is allocated. 1976*4219Smcpowers * For EC public keys, it is CKA_EC_PARAMS and CKA_EC_POINT. 1977*4219Smcpowers * For EC private keys, it is CKA_EC_PARAMS and CKA_VALUE. 1978*4219Smcpowers */ 1979*4219Smcpowers static int 1980*4219Smcpowers get_base_key_attributes(kernel_object_t *base_key, crypto_key_t *key_by_value) 1981*4219Smcpowers { 1982*4219Smcpowers CK_ATTRIBUTE tmp; 1983*4219Smcpowers crypto_object_attribute_t *attrs; 1984*4219Smcpowers biginteger_t *big; 1985*4219Smcpowers int rv; 1986*4219Smcpowers 1987*4219Smcpowers switch (base_key->key_type) { 1988*4219Smcpowers case CKK_EC: 1989*4219Smcpowers attrs = malloc(2 * sizeof (crypto_object_attribute_t)); 1990*4219Smcpowers if (attrs == NULL) { 1991*4219Smcpowers rv = CKR_HOST_MEMORY; 1992*4219Smcpowers goto out; 1993*4219Smcpowers } 1994*4219Smcpowers bzero(attrs, 2 * sizeof (crypto_object_attribute_t)); 1995*4219Smcpowers 1996*4219Smcpowers (void) pthread_mutex_lock(&base_key->object_mutex); 1997*4219Smcpowers 1998*4219Smcpowers if (!base_key->is_lib_obj) { 1999*4219Smcpowers rv = CRYPTO_ARGUMENTS_BAD; 2000*4219Smcpowers goto out; 2001*4219Smcpowers } 2002*4219Smcpowers 2003*4219Smcpowers if (base_key->class != CKO_PUBLIC_KEY && 2004*4219Smcpowers base_key->class != CKO_PRIVATE_KEY) { 2005*4219Smcpowers rv = CRYPTO_ARGUMENTS_BAD; 2006*4219Smcpowers goto out; 2007*4219Smcpowers } 2008*4219Smcpowers 2009*4219Smcpowers /* 2010*4219Smcpowers * Both public and private EC keys should have 2011*4219Smcpowers * a CKA_EC_PARAMS attribute. 2012*4219Smcpowers */ 2013*4219Smcpowers tmp.type = CKA_EC_PARAMS; 2014*4219Smcpowers tmp.pValue = NULL; 2015*4219Smcpowers 2016*4219Smcpowers /* get size of attribute */ 2017*4219Smcpowers rv = kernel_get_attribute(base_key, &tmp); 2018*4219Smcpowers if (rv != CKR_OK) { 2019*4219Smcpowers goto out; 2020*4219Smcpowers } 2021*4219Smcpowers 2022*4219Smcpowers tmp.pValue = malloc(tmp.ulValueLen); 2023*4219Smcpowers if (tmp.pValue == NULL) { 2024*4219Smcpowers rv = CKR_HOST_MEMORY; 2025*4219Smcpowers goto out; 2026*4219Smcpowers } 2027*4219Smcpowers rv = kernel_get_attribute(base_key, &tmp); 2028*4219Smcpowers if (rv != CKR_OK) { 2029*4219Smcpowers goto out; 2030*4219Smcpowers } 2031*4219Smcpowers attrs[0].oa_type = tmp.type; 2032*4219Smcpowers attrs[0].oa_value = tmp.pValue; 2033*4219Smcpowers attrs[0].oa_value_len = tmp.ulValueLen; 2034*4219Smcpowers 2035*4219Smcpowers switch (base_key->class) { 2036*4219Smcpowers case CKO_PUBLIC_KEY: 2037*4219Smcpowers big = OBJ_PUB_EC_POINT(base_key); 2038*4219Smcpowers tmp.type = CKA_EC_POINT; 2039*4219Smcpowers break; 2040*4219Smcpowers 2041*4219Smcpowers case CKO_PRIVATE_KEY: 2042*4219Smcpowers big = OBJ_PRI_EC_VALUE(base_key); 2043*4219Smcpowers tmp.type = CKA_VALUE; 2044*4219Smcpowers break; 2045*4219Smcpowers 2046*4219Smcpowers default: 2047*4219Smcpowers rv = CKR_ATTRIBUTE_TYPE_INVALID; 2048*4219Smcpowers goto out; 2049*4219Smcpowers } 2050*4219Smcpowers tmp.ulValueLen = big->big_value_len; 2051*4219Smcpowers tmp.pValue = malloc(tmp.ulValueLen); 2052*4219Smcpowers if (tmp.pValue == NULL) { 2053*4219Smcpowers rv = CKR_HOST_MEMORY; 2054*4219Smcpowers goto out; 2055*4219Smcpowers } 2056*4219Smcpowers rv = kernel_get_attribute(base_key, &tmp); 2057*4219Smcpowers if (rv != CKR_OK) { 2058*4219Smcpowers goto out; 2059*4219Smcpowers } 2060*4219Smcpowers attrs[1].oa_type = tmp.type; 2061*4219Smcpowers attrs[1].oa_value = tmp.pValue; 2062*4219Smcpowers attrs[1].oa_value_len = tmp.ulValueLen; 2063*4219Smcpowers key_by_value->ck_attrs = attrs; 2064*4219Smcpowers key_by_value->ck_count = 2; 2065*4219Smcpowers break; 2066*4219Smcpowers 2067*4219Smcpowers case CKK_DH: 2068*4219Smcpowers attrs = malloc(3 * sizeof (crypto_object_attribute_t)); 2069*4219Smcpowers if (attrs == NULL) { 2070*4219Smcpowers rv = CKR_HOST_MEMORY; 2071*4219Smcpowers goto out; 2072*4219Smcpowers } 2073*4219Smcpowers bzero(attrs, 3 * sizeof (crypto_object_attribute_t)); 2074*4219Smcpowers 2075*4219Smcpowers (void) pthread_mutex_lock(&base_key->object_mutex); 2076*4219Smcpowers 2077*4219Smcpowers if (!base_key->is_lib_obj) { 2078*4219Smcpowers rv = CRYPTO_ARGUMENTS_BAD; 2079*4219Smcpowers goto out; 2080*4219Smcpowers } 2081*4219Smcpowers 2082*4219Smcpowers if (base_key->class != CKO_PRIVATE_KEY) { 2083*4219Smcpowers rv = CRYPTO_ARGUMENTS_BAD; 2084*4219Smcpowers goto out; 2085*4219Smcpowers } 2086*4219Smcpowers tmp.type = CKA_BASE; 2087*4219Smcpowers tmp.pValue = NULL; 2088*4219Smcpowers 2089*4219Smcpowers /* get size of attribute */ 2090*4219Smcpowers rv = kernel_get_attribute(base_key, &tmp); 2091*4219Smcpowers if (rv != CKR_OK) { 2092*4219Smcpowers goto out; 2093*4219Smcpowers } 2094*4219Smcpowers 2095*4219Smcpowers tmp.pValue = malloc(tmp.ulValueLen); 2096*4219Smcpowers if (tmp.pValue == NULL) { 2097*4219Smcpowers rv = CKR_HOST_MEMORY; 2098*4219Smcpowers goto out; 2099*4219Smcpowers } 2100*4219Smcpowers rv = kernel_get_attribute(base_key, &tmp); 2101*4219Smcpowers if (rv != CKR_OK) { 2102*4219Smcpowers goto out; 2103*4219Smcpowers } 2104*4219Smcpowers attrs[0].oa_type = tmp.type; 2105*4219Smcpowers attrs[0].oa_value = tmp.pValue; 2106*4219Smcpowers attrs[0].oa_value_len = tmp.ulValueLen; 2107*4219Smcpowers 2108*4219Smcpowers tmp.type = CKA_PRIME; 2109*4219Smcpowers tmp.pValue = NULL; 2110*4219Smcpowers 2111*4219Smcpowers /* get size of attribute */ 2112*4219Smcpowers rv = kernel_get_attribute(base_key, &tmp); 2113*4219Smcpowers if (rv != CKR_OK) { 2114*4219Smcpowers goto out; 2115*4219Smcpowers } 2116*4219Smcpowers 2117*4219Smcpowers tmp.pValue = malloc(tmp.ulValueLen); 2118*4219Smcpowers if (tmp.pValue == NULL) { 2119*4219Smcpowers rv = CKR_HOST_MEMORY; 2120*4219Smcpowers goto out; 2121*4219Smcpowers } 2122*4219Smcpowers rv = kernel_get_attribute(base_key, &tmp); 2123*4219Smcpowers if (rv != CKR_OK) { 2124*4219Smcpowers goto out; 2125*4219Smcpowers } 2126*4219Smcpowers attrs[1].oa_type = tmp.type; 2127*4219Smcpowers attrs[1].oa_value = tmp.pValue; 2128*4219Smcpowers attrs[1].oa_value_len = tmp.ulValueLen; 2129*4219Smcpowers 2130*4219Smcpowers big = OBJ_PRI_EC_VALUE(base_key); 2131*4219Smcpowers tmp.type = CKA_VALUE; 2132*4219Smcpowers 2133*4219Smcpowers tmp.ulValueLen = big->big_value_len; 2134*4219Smcpowers tmp.pValue = malloc(tmp.ulValueLen); 2135*4219Smcpowers if (tmp.pValue == NULL) { 2136*4219Smcpowers rv = CKR_HOST_MEMORY; 2137*4219Smcpowers goto out; 2138*4219Smcpowers } 2139*4219Smcpowers rv = kernel_get_attribute(base_key, &tmp); 2140*4219Smcpowers if (rv != CKR_OK) { 2141*4219Smcpowers goto out; 2142*4219Smcpowers } 2143*4219Smcpowers attrs[2].oa_type = tmp.type; 2144*4219Smcpowers attrs[2].oa_value = tmp.pValue; 2145*4219Smcpowers attrs[2].oa_value_len = tmp.ulValueLen; 2146*4219Smcpowers key_by_value->ck_attrs = attrs; 2147*4219Smcpowers key_by_value->ck_count = 3; 2148*4219Smcpowers break; 2149*4219Smcpowers 2150*4219Smcpowers default: 2151*4219Smcpowers rv = CKR_ATTRIBUTE_TYPE_INVALID; 2152*4219Smcpowers goto out; 2153*4219Smcpowers } 2154*4219Smcpowers (void) pthread_mutex_unlock(&base_key->object_mutex); 2155*4219Smcpowers return (CKR_OK); 2156*4219Smcpowers 2157*4219Smcpowers out: 2158*4219Smcpowers (void) pthread_mutex_unlock(&base_key->object_mutex); 2159*4219Smcpowers return (rv); 2160*4219Smcpowers } 2161*4219Smcpowers 2162*4219Smcpowers CK_RV 2163*4219Smcpowers derive_key_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, 2164*4219Smcpowers CK_ULONG ulAttributeCount, kernel_session_t *session_p, 2165*4219Smcpowers crypto_mech_type_t k_mech_type, kernel_object_t *basekey_p, 2166*4219Smcpowers kernel_object_t *new_objp) 2167*4219Smcpowers { 2168*4219Smcpowers crypto_nostore_derive_key_t obj_ndk; 2169*4219Smcpowers char *key_buf = NULL; 2170*4219Smcpowers CK_ATTRIBUTE_PTR newTemplate = NULL; 2171*4219Smcpowers CK_BBOOL is_token_obj = FALSE; 2172*4219Smcpowers CK_RV rv = CKR_OK; 2173*4219Smcpowers CK_ULONG secret_class = CKO_SECRET_KEY; 2174*4219Smcpowers ulong_t key_len = 0; 2175*4219Smcpowers uint_t attr_count = 0; 2176*4219Smcpowers boolean_t removed; 2177*4219Smcpowers boolean_t has_class; 2178*4219Smcpowers int r, n; 2179*4219Smcpowers 2180*4219Smcpowers obj_ndk.ndk_in_count = 0; 2181*4219Smcpowers obj_ndk.ndk_out_count = 0; 2182*4219Smcpowers obj_ndk.ndk_base_key.ck_count = 0; 2183*4219Smcpowers 2184*4219Smcpowers rv = get_key_len_from_template(pMechanism, pTemplate, ulAttributeCount, 2185*4219Smcpowers basekey_p, &key_len); 2186*4219Smcpowers if (rv != CKR_OK) { 2187*4219Smcpowers goto failed_exit; 2188*4219Smcpowers } 2189*4219Smcpowers 2190*4219Smcpowers if ((key_buf = malloc(key_len)) == NULL) { 2191*4219Smcpowers rv = CKR_HOST_MEMORY; 2192*4219Smcpowers goto failed_exit; 2193*4219Smcpowers } 2194*4219Smcpowers 2195*4219Smcpowers has_class = attribute_in_template(CKA_CLASS, pTemplate, 2196*4219Smcpowers ulAttributeCount); 2197*4219Smcpowers 2198*4219Smcpowers attr_count = ulAttributeCount + 1; 2199*4219Smcpowers if (!has_class) 2200*4219Smcpowers attr_count++; 2201*4219Smcpowers 2202*4219Smcpowers newTemplate = grow_template(pTemplate, ulAttributeCount, attr_count); 2203*4219Smcpowers if (newTemplate == NULL) { 2204*4219Smcpowers rv = CKR_HOST_MEMORY; 2205*4219Smcpowers goto failed_exit; 2206*4219Smcpowers } 2207*4219Smcpowers 2208*4219Smcpowers n = ulAttributeCount; 2209*4219Smcpowers if (!has_class) { 2210*4219Smcpowers newTemplate[n].type = CKA_CLASS; 2211*4219Smcpowers newTemplate[n].pValue = (caddr_t)&secret_class; 2212*4219Smcpowers newTemplate[n].ulValueLen = sizeof (secret_class); 2213*4219Smcpowers n++; 2214*4219Smcpowers } 2215*4219Smcpowers 2216*4219Smcpowers /* Add CKA_VALUE to the template */ 2217*4219Smcpowers newTemplate[n].type = CKA_VALUE; 2218*4219Smcpowers newTemplate[n].pValue = (caddr_t)key_buf; 2219*4219Smcpowers newTemplate[n].ulValueLen = key_len; 2220*4219Smcpowers 2221*4219Smcpowers rv = process_object_attributes(newTemplate, attr_count - 1, 2222*4219Smcpowers &obj_ndk.ndk_in_attributes, &is_token_obj); 2223*4219Smcpowers if (rv != CKR_OK) { 2224*4219Smcpowers goto failed_exit; 2225*4219Smcpowers } 2226*4219Smcpowers 2227*4219Smcpowers rv = process_object_attributes(&newTemplate[attr_count - 1], 2228*4219Smcpowers 1, &obj_ndk.ndk_out_attributes, &is_token_obj); 2229*4219Smcpowers if (rv != CKR_OK) { 2230*4219Smcpowers goto failed_exit; 2231*4219Smcpowers } 2232*4219Smcpowers 2233*4219Smcpowers /* Cannot create a token object with a READ-ONLY session. */ 2234*4219Smcpowers if (is_token_obj && session_p->ses_RO) { 2235*4219Smcpowers rv = CKR_SESSION_READ_ONLY; 2236*4219Smcpowers goto failed_exit; 2237*4219Smcpowers } 2238*4219Smcpowers 2239*4219Smcpowers obj_ndk.ndk_session = session_p->k_session; 2240*4219Smcpowers obj_ndk.ndk_mechanism.cm_type = k_mech_type; 2241*4219Smcpowers obj_ndk.ndk_mechanism.cm_param = pMechanism->pParameter; 2242*4219Smcpowers obj_ndk.ndk_mechanism.cm_param_len = pMechanism->ulParameterLen; 2243*4219Smcpowers 2244*4219Smcpowers /* 2245*4219Smcpowers * Obtain the attributes of base key and pass them by value. 2246*4219Smcpowers */ 2247*4219Smcpowers rv = get_base_key_attributes(basekey_p, &obj_ndk.ndk_base_key); 2248*4219Smcpowers if (rv != CKR_OK) { 2249*4219Smcpowers goto failed_exit; 2250*4219Smcpowers } 2251*4219Smcpowers 2252*4219Smcpowers obj_ndk.ndk_base_key.ck_format = CRYPTO_KEY_ATTR_LIST; 2253*4219Smcpowers obj_ndk.ndk_in_count = attr_count - 1; 2254*4219Smcpowers obj_ndk.ndk_out_count = 1; 2255*4219Smcpowers 2256*4219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_DERIVE_KEY, 2257*4219Smcpowers &obj_ndk)) < 0) { 2258*4219Smcpowers if (errno != EINTR) 2259*4219Smcpowers break; 2260*4219Smcpowers } 2261*4219Smcpowers if (r < 0) { 2262*4219Smcpowers rv = CKR_FUNCTION_FAILED; 2263*4219Smcpowers } else { 2264*4219Smcpowers rv = crypto2pkcs11_error_number(obj_ndk.ndk_return_value); 2265*4219Smcpowers } 2266*4219Smcpowers free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count); 2267*4219Smcpowers free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs, 2268*4219Smcpowers &obj_ndk.ndk_base_key.ck_count); 2269*4219Smcpowers if (rv != CKR_OK) { 2270*4219Smcpowers goto failed_exit; 2271*4219Smcpowers } 2272*4219Smcpowers 2273*4219Smcpowers rv = get_object_attributes(&newTemplate[attr_count - 1], 2274*4219Smcpowers 1, obj_ndk.ndk_out_attributes); 2275*4219Smcpowers free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count); 2276*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 2277*4219Smcpowers goto failed_exit; 2278*4219Smcpowers } 2279*4219Smcpowers 2280*4219Smcpowers removed = remove_one_attribute(newTemplate, CKA_VALUE_LEN, 2281*4219Smcpowers attr_count, B_FALSE); 2282*4219Smcpowers 2283*4219Smcpowers rv = kernel_build_object(newTemplate, removed ? attr_count - 1 : 2284*4219Smcpowers attr_count, new_objp, session_p, KERNEL_GEN_KEY); 2285*4219Smcpowers if (rv != CRYPTO_SUCCESS) { 2286*4219Smcpowers goto failed_exit; 2287*4219Smcpowers } 2288*4219Smcpowers 2289*4219Smcpowers free(key_buf); 2290*4219Smcpowers free(newTemplate); 2291*4219Smcpowers new_objp->is_lib_obj = B_TRUE; 2292*4219Smcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 2293*4219Smcpowers return (CKR_OK); 2294*4219Smcpowers 2295*4219Smcpowers failed_exit: 2296*4219Smcpowers if (key_buf != NULL) 2297*4219Smcpowers free(key_buf); 2298*4219Smcpowers if (newTemplate != NULL) 2299*4219Smcpowers free(newTemplate); 2300*4219Smcpowers free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count); 2301*4219Smcpowers free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count); 2302*4219Smcpowers free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs, 2303*4219Smcpowers &obj_ndk.ndk_base_key.ck_count); 2304*4219Smcpowers return (rv); 2305*4219Smcpowers } 23060Sstevel@tonic-gate 23070Sstevel@tonic-gate CK_RV 23080Sstevel@tonic-gate C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 23090Sstevel@tonic-gate CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, 23100Sstevel@tonic-gate CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) 23110Sstevel@tonic-gate { 23120Sstevel@tonic-gate CK_RV rv = CKR_OK; 23130Sstevel@tonic-gate kernel_session_t *session_p; 23140Sstevel@tonic-gate kernel_object_t *basekey_p; 23150Sstevel@tonic-gate kernel_object_t *new_objp; 23160Sstevel@tonic-gate kernel_slot_t *pslot; 23170Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 23180Sstevel@tonic-gate CK_BBOOL is_pri_obj; 23190Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE; 23200Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 23210Sstevel@tonic-gate int r; 23220Sstevel@tonic-gate 23230Sstevel@tonic-gate if (!kernel_initialized) 23240Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 23250Sstevel@tonic-gate 23260Sstevel@tonic-gate /* Obtain the session pointer. */ 23270Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 23280Sstevel@tonic-gate if (rv != CKR_OK) 23290Sstevel@tonic-gate return (rv); 23300Sstevel@tonic-gate 2331872Sizick if (pMechanism == NULL) { 2332214Smcpowers REFRELE(session_p, ses_lock_held); 2333214Smcpowers return (CKR_ARGUMENTS_BAD); 23340Sstevel@tonic-gate } 23350Sstevel@tonic-gate 23360Sstevel@tonic-gate if ((pTemplate == NULL && ulAttributeCount != 0) || 23370Sstevel@tonic-gate (pTemplate != NULL && ulAttributeCount == 0)) { 2338214Smcpowers REFRELE(session_p, ses_lock_held); 2339214Smcpowers return (CKR_ARGUMENTS_BAD); 23400Sstevel@tonic-gate } 23410Sstevel@tonic-gate 23420Sstevel@tonic-gate /* Obtain the base key object pointer. */ 23430Sstevel@tonic-gate HANDLE2OBJECT(hBaseKey, basekey_p, rv); 23440Sstevel@tonic-gate if (rv != CKR_OK) { 2345214Smcpowers REFRELE(session_p, ses_lock_held); 2346214Smcpowers return (rv); 23470Sstevel@tonic-gate } 23480Sstevel@tonic-gate 23490Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 23500Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 23510Sstevel@tonic-gate if (rv != CKR_OK) { 23520Sstevel@tonic-gate goto failed_exit; 23530Sstevel@tonic-gate } 23540Sstevel@tonic-gate 23550Sstevel@tonic-gate /* Create an object wrapper in the library for the generated key. */ 23560Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t)); 23570Sstevel@tonic-gate if (new_objp == NULL) { 23580Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 23590Sstevel@tonic-gate goto failed_exit; 23600Sstevel@tonic-gate } 23610Sstevel@tonic-gate 2362*4219Smcpowers /* 2363*4219Smcpowers * Special Case: if token does not support object creation, 2364*4219Smcpowers * but does support key derivation by value, then create a session 2365*4219Smcpowers * object and initialize with values returned by token. 2366*4219Smcpowers */ 2367*4219Smcpowers pslot = slot_table[session_p->ses_slotid]; 2368*4219Smcpowers if (!pslot->sl_func_list.fl_object_create) { 2369*4219Smcpowers rv = derive_key_by_value(pMechanism, pTemplate, 2370*4219Smcpowers ulAttributeCount, session_p, k_mech_type, basekey_p, 2371*4219Smcpowers new_objp); 2372*4219Smcpowers if (rv != CKR_OK) 2373*4219Smcpowers goto failed_exit; 2374*4219Smcpowers } else { 2375*4219Smcpowers crypto_derive_key_t obj_dk; 23760Sstevel@tonic-gate 2377*4219Smcpowers rv = process_object_attributes(pTemplate, ulAttributeCount, 2378*4219Smcpowers &obj_dk.dk_attributes, &is_token_obj); 2379*4219Smcpowers if (rv != CKR_OK) { 2380*4219Smcpowers goto failed_exit; 2381*4219Smcpowers } 2382*4219Smcpowers 2383*4219Smcpowers /* Cannot create a token object with a READ-ONLY session. */ 2384*4219Smcpowers if (is_token_obj && session_p->ses_RO) { 2385*4219Smcpowers free_object_attributes(obj_dk.dk_attributes, 2386*4219Smcpowers ulAttributeCount); 2387*4219Smcpowers rv = CKR_SESSION_READ_ONLY; 2388*4219Smcpowers goto failed_exit; 2389*4219Smcpowers } 2390*4219Smcpowers 2391*4219Smcpowers obj_dk.dk_session = session_p->k_session; 2392*4219Smcpowers obj_dk.dk_mechanism.cm_type = k_mech_type; 2393*4219Smcpowers obj_dk.dk_mechanism.cm_param = pMechanism->pParameter; 2394*4219Smcpowers obj_dk.dk_mechanism.cm_param_len = pMechanism->ulParameterLen; 2395*4219Smcpowers obj_dk.dk_base_key.ck_format = CRYPTO_KEY_REFERENCE; 2396*4219Smcpowers obj_dk.dk_base_key.ck_obj_id = basekey_p->k_handle; 2397*4219Smcpowers obj_dk.dk_count = ulAttributeCount; 23980Sstevel@tonic-gate 2399*4219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_DERIVE_KEY, &obj_dk)) < 0) { 2400*4219Smcpowers if (errno != EINTR) 2401*4219Smcpowers break; 2402*4219Smcpowers } 2403*4219Smcpowers if (r < 0) { 2404*4219Smcpowers rv = CKR_FUNCTION_FAILED; 2405*4219Smcpowers } else { 2406*4219Smcpowers rv = crypto2pkcs11_error_number(obj_dk.dk_return_value); 2407*4219Smcpowers } 2408*4219Smcpowers 2409*4219Smcpowers free_object_attributes(obj_dk.dk_attributes, ulAttributeCount); 2410*4219Smcpowers if (rv != CKR_OK) { 2411*4219Smcpowers goto failed_exit; 2412*4219Smcpowers } 24130Sstevel@tonic-gate 2414*4219Smcpowers /* Get the CKA_PRIVATE value for the derived key. */ 2415*4219Smcpowers rv = get_cka_private_value(session_p, obj_dk.dk_object_handle, 2416*4219Smcpowers &is_pri_obj); 2417*4219Smcpowers if (rv != CKR_OK) { 2418*4219Smcpowers goto failed_exit; 2419*4219Smcpowers } 2420*4219Smcpowers 2421*4219Smcpowers /* 2422*4219Smcpowers * Store the kernel object handle into the new derived key 2423*4219Smcpowers * object and finish the object initialization. 2424*4219Smcpowers */ 2425*4219Smcpowers new_objp->is_lib_obj = B_FALSE; 2426*4219Smcpowers new_objp->k_handle = obj_dk.dk_object_handle; 2427*4219Smcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 2428*4219Smcpowers new_objp->extra_attrlistp = NULL; 2429*4219Smcpowers 2430*4219Smcpowers if (is_pri_obj) 2431*4219Smcpowers new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 2432*4219Smcpowers else 2433*4219Smcpowers new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 2434*4219Smcpowers 2435*4219Smcpowers if (is_token_obj) 2436*4219Smcpowers new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 2437*4219Smcpowers else 2438*4219Smcpowers new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 24390Sstevel@tonic-gate } 24400Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 24410Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 24420Sstevel@tonic-gate 24430Sstevel@tonic-gate /* 24440Sstevel@tonic-gate * Add the new derived object to the slot's token list if it is a 24450Sstevel@tonic-gate * token object. Otherwise, add it to the session's object list. 24460Sstevel@tonic-gate */ 24470Sstevel@tonic-gate if (is_token_obj) { 24480Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 24490Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot); 24500Sstevel@tonic-gate } else { 24510Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p); 24520Sstevel@tonic-gate } 24530Sstevel@tonic-gate 24540Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp; 2455214Smcpowers OBJ_REFRELE(basekey_p); 24560Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 24570Sstevel@tonic-gate return (rv); 24580Sstevel@tonic-gate 24590Sstevel@tonic-gate failed_exit: 2460214Smcpowers OBJ_REFRELE(basekey_p); 24610Sstevel@tonic-gate if (new_objp != NULL) { 24620Sstevel@tonic-gate (void) free(new_objp); 24630Sstevel@tonic-gate } 24640Sstevel@tonic-gate 24650Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 24660Sstevel@tonic-gate return (rv); 24670Sstevel@tonic-gate } 2468