17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*034448feSmcpowers * Common Development and Distribution License (the "License"). 6*034448feSmcpowers * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*034448feSmcpowers * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <strings.h> 297c478bd9Sstevel@tonic-gate #include <errno.h> 307c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 317c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h> 327c478bd9Sstevel@tonic-gate #include "kernelGlobal.h" 337c478bd9Sstevel@tonic-gate #include "kernelSession.h" 347c478bd9Sstevel@tonic-gate #include "kernelObject.h" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate static boolean_t 37*034448feSmcpowers attribute_in_template(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR t, CK_ULONG cnt) 38*034448feSmcpowers { 39*034448feSmcpowers int i; 40*034448feSmcpowers 41*034448feSmcpowers for (i = 0; i < cnt; i++) { 42*034448feSmcpowers if (t[i].type == type) 43*034448feSmcpowers return (B_TRUE); 44*034448feSmcpowers } 45*034448feSmcpowers return (B_FALSE); 46*034448feSmcpowers } 47*034448feSmcpowers 48*034448feSmcpowers /* 49*034448feSmcpowers * This routine returns modulus bytes rounded up to the nearest 8 byte 50*034448feSmcpowers * chunk. This is so we don't have to pass in max sized buffers for 51*034448feSmcpowers * returned attributes. Every unnecessary byte that we pass in results 52*034448feSmcpowers * in a kernel allocation. 53*034448feSmcpowers */ 54*034448feSmcpowers static ulong_t 55*034448feSmcpowers get_modulus_bytes(CK_ATTRIBUTE_PTR t, CK_ULONG cnt) 56*034448feSmcpowers { 57*034448feSmcpowers CK_ULONG modulus_len; 58*034448feSmcpowers int i; 59*034448feSmcpowers 60*034448feSmcpowers for (i = 0; i < cnt; i++) { 61*034448feSmcpowers if (t[i].type == CKA_MODULUS_BITS) { 62*034448feSmcpowers get_ulong_attr_from_template(&modulus_len, &t[i]); 63*034448feSmcpowers /* convert from bit length to byte length */ 64*034448feSmcpowers modulus_len = (modulus_len - 1) / 64 + 1; 65*034448feSmcpowers return (modulus_len * 8); 66*034448feSmcpowers } 67*034448feSmcpowers } 68*034448feSmcpowers return (0); 69*034448feSmcpowers } 70*034448feSmcpowers 71*034448feSmcpowers /* 72*034448feSmcpowers * Remove specified attribute from array. Storage for the attribute's 73*034448feSmcpowers * value is freed if 'free_attr' is TRUE. Attributes are shifted so they are 74*034448feSmcpowers * contiguous within the array, i.e. the next attribute is shifted into 75*034448feSmcpowers * the position of the removed attribute. Returns TRUE if specified 76*034448feSmcpowers * attribute is removed. 77*034448feSmcpowers */ 78*034448feSmcpowers static boolean_t 79*034448feSmcpowers remove_one_attribute(CK_ATTRIBUTE_PTR t, CK_ULONG type, uint_t count, 80*034448feSmcpowers boolean_t free_attr) 81*034448feSmcpowers { 82*034448feSmcpowers int i, j; 83*034448feSmcpowers 84*034448feSmcpowers for (i = 0, j = 0; i < count; i++) { 85*034448feSmcpowers if (t[i].type == type) { 86*034448feSmcpowers if (free_attr) { 87*034448feSmcpowers free(t[i].pValue); 88*034448feSmcpowers } 89*034448feSmcpowers continue; 90*034448feSmcpowers } 91*034448feSmcpowers if (i != j) { 92*034448feSmcpowers t[j].type = t[i].type; 93*034448feSmcpowers t[j].pValue = t[i].pValue; 94*034448feSmcpowers t[j].ulValueLen = t[i].ulValueLen; 95*034448feSmcpowers } 96*034448feSmcpowers j++; 97*034448feSmcpowers } 98*034448feSmcpowers if (j == count) 99*034448feSmcpowers return (B_FALSE); 100*034448feSmcpowers 101*034448feSmcpowers /* safety */ 102*034448feSmcpowers t[j].pValue = NULL; 103*034448feSmcpowers t[j].ulValueLen = 0; 104*034448feSmcpowers return (B_TRUE); 105*034448feSmcpowers } 106*034448feSmcpowers 107*034448feSmcpowers static boolean_t 1087c478bd9Sstevel@tonic-gate is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount) 1097c478bd9Sstevel@tonic-gate { 1107c478bd9Sstevel@tonic-gate int i; 1117c478bd9Sstevel@tonic-gate for (i = 0; i < ulAttributeCount; i++) { 1127c478bd9Sstevel@tonic-gate if (pTemplate[i].type == CKA_CLASS && 1137c478bd9Sstevel@tonic-gate *(CK_OBJECT_CLASS *)(pTemplate[i].pValue) == 1147c478bd9Sstevel@tonic-gate CKO_SECRET_KEY) 1157c478bd9Sstevel@tonic-gate return (B_TRUE); 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate return (B_FALSE); 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 120*034448feSmcpowers /* 121*034448feSmcpowers * Allocate a template with space for new_count entries and copy the 122*034448feSmcpowers * specified template into the new template. 123*034448feSmcpowers */ 124*034448feSmcpowers static CK_ATTRIBUTE_PTR 125*034448feSmcpowers grow_template(CK_ATTRIBUTE_PTR old_template, CK_ULONG old_count, 126*034448feSmcpowers CK_ULONG new_count) 127*034448feSmcpowers { 128*034448feSmcpowers CK_ATTRIBUTE_PTR new_template; 129*034448feSmcpowers 130*034448feSmcpowers new_template = malloc(new_count * sizeof (CK_ATTRIBUTE)); 131*034448feSmcpowers if (new_template != NULL) 132*034448feSmcpowers bcopy(old_template, new_template, 133*034448feSmcpowers old_count * sizeof (CK_ATTRIBUTE)); 134*034448feSmcpowers return (new_template); 135*034448feSmcpowers } 136*034448feSmcpowers 137*034448feSmcpowers /* 138*034448feSmcpowers * For fixed length keys such as DES, return the length based on 139*034448feSmcpowers * the key type. For variable length keys such as AES, take the 140*034448feSmcpowers * length from the CKA_VALUE_LEN attribute. 141*034448feSmcpowers */ 142*034448feSmcpowers static int 143*034448feSmcpowers get_key_len_from_template(CK_MECHANISM_PTR pMechanism, 144*034448feSmcpowers CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, 145*034448feSmcpowers kernel_object_t *basekey_p, ulong_t *key_len) 146*034448feSmcpowers { 147*034448feSmcpowers boolean_t fixed_len_key = B_FALSE; 148*034448feSmcpowers ulong_t key_type; 149*034448feSmcpowers int i; 150*034448feSmcpowers 151*034448feSmcpowers for (i = 0; i < ulAttributeCount; i++) { 152*034448feSmcpowers if (pTemplate[i].type == CKA_KEY_TYPE) { 153*034448feSmcpowers get_ulong_attr_from_template(&key_type, &pTemplate[i]); 154*034448feSmcpowers break; 155*034448feSmcpowers } 156*034448feSmcpowers } 157*034448feSmcpowers /* CKA_KEY_TYPE must be present */ 158*034448feSmcpowers if (i == ulAttributeCount) 159*034448feSmcpowers return (CKR_TEMPLATE_INCOMPLETE); 160*034448feSmcpowers 161*034448feSmcpowers switch (key_type) { 162*034448feSmcpowers case CKK_DES: 163*034448feSmcpowers *key_len = 8; 164*034448feSmcpowers fixed_len_key = B_TRUE; 165*034448feSmcpowers break; 166*034448feSmcpowers case CKK_DES3: 167*034448feSmcpowers *key_len = 24; 168*034448feSmcpowers fixed_len_key = B_TRUE; 169*034448feSmcpowers break; 170*034448feSmcpowers case CKK_AES: 171*034448feSmcpowers case CKK_BLOWFISH: 172*034448feSmcpowers for (i = 0; i < ulAttributeCount; i++) { 173*034448feSmcpowers if (pTemplate[i].type == CKA_VALUE_LEN) { 174*034448feSmcpowers get_ulong_attr_from_template(key_len, 175*034448feSmcpowers &pTemplate[i]); 176*034448feSmcpowers break; 177*034448feSmcpowers } 178*034448feSmcpowers } 179*034448feSmcpowers /* CKA_VALUE_LEN must be present */ 180*034448feSmcpowers if (i == ulAttributeCount) 181*034448feSmcpowers return (CKR_TEMPLATE_INCOMPLETE); 182*034448feSmcpowers break; 183*034448feSmcpowers case CKK_GENERIC_SECRET: 184*034448feSmcpowers /* 185*034448feSmcpowers * The key will not be truncated, so we need to 186*034448feSmcpowers * get the max length for the mechanism. 187*034448feSmcpowers */ 188*034448feSmcpowers if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE) { 189*034448feSmcpowers CK_ATTRIBUTE tmp; 190*034448feSmcpowers 191*034448feSmcpowers tmp.type = CKA_PRIME; 192*034448feSmcpowers tmp.pValue = NULL; 193*034448feSmcpowers 194*034448feSmcpowers /* get size of attribute */ 195*034448feSmcpowers if (kernel_get_attribute(basekey_p, &tmp) != CKR_OK) { 196*034448feSmcpowers return (CKR_ARGUMENTS_BAD); 197*034448feSmcpowers } 198*034448feSmcpowers *key_len = tmp.ulValueLen; 199*034448feSmcpowers } else { 200*034448feSmcpowers return (CKR_ARGUMENTS_BAD); 201*034448feSmcpowers } 202*034448feSmcpowers break; 203*034448feSmcpowers default: 204*034448feSmcpowers return (CKR_ATTRIBUTE_VALUE_INVALID); 205*034448feSmcpowers } 206*034448feSmcpowers 207*034448feSmcpowers if (fixed_len_key && attribute_in_template(CKA_VALUE_LEN, 208*034448feSmcpowers pTemplate, ulAttributeCount)) 209*034448feSmcpowers return (CKR_TEMPLATE_INCONSISTENT); 210*034448feSmcpowers 211*034448feSmcpowers return (CKR_OK); 212*034448feSmcpowers } 213*034448feSmcpowers 214*034448feSmcpowers /* find specified attribute src template and copy to dest */ 215*034448feSmcpowers static int 216*034448feSmcpowers copy_attribute(CK_ULONG type, CK_ATTRIBUTE_PTR src, CK_ULONG src_cnt, 217*034448feSmcpowers CK_ATTRIBUTE_PTR dst) 218*034448feSmcpowers { 219*034448feSmcpowers int rv, i; 220*034448feSmcpowers 221*034448feSmcpowers for (i = 0; i < src_cnt; i++) { 222*034448feSmcpowers if (src[i].type == type) { 223*034448feSmcpowers rv = get_string_from_template(dst, &src[i]); 224*034448feSmcpowers break; 225*034448feSmcpowers } 226*034448feSmcpowers } 227*034448feSmcpowers /* 228*034448feSmcpowers * The public template didn't have attribute. 229*034448feSmcpowers */ 230*034448feSmcpowers if (i == src_cnt) { 231*034448feSmcpowers rv = CKR_TEMPLATE_INCOMPLETE; 232*034448feSmcpowers } 233*034448feSmcpowers return (rv); 234*034448feSmcpowers } 235*034448feSmcpowers 236*034448feSmcpowers static void 237*034448feSmcpowers free_attributes(caddr_t p, uint_t *countp) 238*034448feSmcpowers { 239*034448feSmcpowers if (*countp > 0) { 240*034448feSmcpowers free_object_attributes(p, *countp); 241*034448feSmcpowers *countp = 0; 242*034448feSmcpowers } 243*034448feSmcpowers } 244*034448feSmcpowers 245*034448feSmcpowers CK_RV 246*034448feSmcpowers key_gen_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, 247*034448feSmcpowers CK_ULONG ulCount, kernel_session_t *session_p, 248*034448feSmcpowers crypto_mech_type_t k_mech_type, kernel_object_t *new_objp) 249*034448feSmcpowers { 250*034448feSmcpowers crypto_nostore_generate_key_t obj_ngk; 251*034448feSmcpowers char *key_buf = NULL; 252*034448feSmcpowers CK_ATTRIBUTE_PTR newTemplate = NULL; 253*034448feSmcpowers CK_BBOOL is_token_obj = FALSE; 254*034448feSmcpowers CK_RV rv = CKR_OK; 255*034448feSmcpowers ulong_t key_len = 0; 256*034448feSmcpowers uint_t attr_count; 257*034448feSmcpowers int r; 258*034448feSmcpowers 259*034448feSmcpowers obj_ngk.ngk_in_count = 0; 260*034448feSmcpowers obj_ngk.ngk_out_count = 0; 261*034448feSmcpowers 262*034448feSmcpowers rv = get_key_len_from_template(pMechanism, pTemplate, ulCount, 263*034448feSmcpowers NULL, &key_len); 264*034448feSmcpowers if (rv != CRYPTO_SUCCESS) 265*034448feSmcpowers goto failed_exit; 266*034448feSmcpowers 267*034448feSmcpowers if ((key_buf = malloc(key_len)) == NULL) { 268*034448feSmcpowers rv = CKR_HOST_MEMORY; 269*034448feSmcpowers goto failed_exit; 270*034448feSmcpowers } 271*034448feSmcpowers 272*034448feSmcpowers attr_count = ulCount + 1; 273*034448feSmcpowers newTemplate = grow_template(pTemplate, ulCount, attr_count); 274*034448feSmcpowers if (newTemplate == NULL) { 275*034448feSmcpowers rv = CKR_HOST_MEMORY; 276*034448feSmcpowers goto failed_exit; 277*034448feSmcpowers } 278*034448feSmcpowers 279*034448feSmcpowers /* Now add the CKA_VALUE attribute to template */ 280*034448feSmcpowers newTemplate[ulCount].type = CKA_VALUE; 281*034448feSmcpowers newTemplate[ulCount].pValue = (caddr_t)key_buf; 282*034448feSmcpowers newTemplate[ulCount].ulValueLen = key_len; 283*034448feSmcpowers 284*034448feSmcpowers rv = process_object_attributes(newTemplate, attr_count - 1, 285*034448feSmcpowers &obj_ngk.ngk_in_attributes, &is_token_obj); 286*034448feSmcpowers if (rv != CKR_OK) { 287*034448feSmcpowers goto failed_exit; 288*034448feSmcpowers } 289*034448feSmcpowers rv = process_object_attributes(&newTemplate[ulCount], 290*034448feSmcpowers 1, &obj_ngk.ngk_out_attributes, &is_token_obj); 291*034448feSmcpowers if (rv != CKR_OK) { 292*034448feSmcpowers goto failed_exit; 293*034448feSmcpowers } 294*034448feSmcpowers 295*034448feSmcpowers /* Cannot create a token object with a READ-ONLY session. */ 296*034448feSmcpowers if (is_token_obj && session_p->ses_RO) { 297*034448feSmcpowers rv = CKR_SESSION_READ_ONLY; 298*034448feSmcpowers goto failed_exit; 299*034448feSmcpowers } 300*034448feSmcpowers 301*034448feSmcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY ioctl */ 302*034448feSmcpowers obj_ngk.ngk_session = session_p->k_session; 303*034448feSmcpowers obj_ngk.ngk_in_count = attr_count - 1; 304*034448feSmcpowers obj_ngk.ngk_out_count = 1; 305*034448feSmcpowers obj_ngk.ngk_mechanism.cm_type = k_mech_type; 306*034448feSmcpowers obj_ngk.ngk_mechanism.cm_param = pMechanism->pParameter; 307*034448feSmcpowers obj_ngk.ngk_mechanism.cm_param_len = pMechanism->ulParameterLen; 308*034448feSmcpowers 309*034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY, 310*034448feSmcpowers &obj_ngk)) < 0) { 311*034448feSmcpowers if (errno != EINTR) 312*034448feSmcpowers break; 313*034448feSmcpowers } 314*034448feSmcpowers if (r < 0) { 315*034448feSmcpowers rv = CKR_FUNCTION_FAILED; 316*034448feSmcpowers } else { 317*034448feSmcpowers rv = crypto2pkcs11_error_number(obj_ngk.ngk_return_value); 318*034448feSmcpowers } 319*034448feSmcpowers free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count); 320*034448feSmcpowers if (rv != CKR_OK) { 321*034448feSmcpowers goto failed_exit; 322*034448feSmcpowers } 323*034448feSmcpowers 324*034448feSmcpowers rv = get_object_attributes(&newTemplate[ulCount], 1, 325*034448feSmcpowers obj_ngk.ngk_out_attributes); 326*034448feSmcpowers free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count); 327*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 328*034448feSmcpowers goto failed_exit; 329*034448feSmcpowers } 330*034448feSmcpowers 331*034448feSmcpowers /* 332*034448feSmcpowers * CKA_VALUE_LEN is not stored with the secret key object, 333*034448feSmcpowers * so we remove it by shifting attributes down one. 334*034448feSmcpowers */ 335*034448feSmcpowers (void) remove_one_attribute(newTemplate, CKA_VALUE_LEN, 336*034448feSmcpowers attr_count, B_FALSE); 337*034448feSmcpowers 338*034448feSmcpowers rv = kernel_build_object(newTemplate, attr_count - 1, 339*034448feSmcpowers new_objp, session_p, KERNEL_GEN_KEY); 340*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 341*034448feSmcpowers goto failed_exit; 342*034448feSmcpowers } 343*034448feSmcpowers new_objp->is_lib_obj = B_TRUE; 344*034448feSmcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 345*034448feSmcpowers (void) free(newTemplate); 346*034448feSmcpowers bzero(key_buf, key_len); 347*034448feSmcpowers (void) free(key_buf); 348*034448feSmcpowers return (CKR_OK); 349*034448feSmcpowers 350*034448feSmcpowers failed_exit: 351*034448feSmcpowers free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count); 352*034448feSmcpowers free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count); 353*034448feSmcpowers if (key_buf != NULL) { 354*034448feSmcpowers bzero(key_buf, key_len); 355*034448feSmcpowers (void) free(key_buf); 356*034448feSmcpowers } 357*034448feSmcpowers if (newTemplate != NULL) { 358*034448feSmcpowers (void) free(newTemplate); 359*034448feSmcpowers } 360*034448feSmcpowers return (rv); 361*034448feSmcpowers } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate CK_RV 3647c478bd9Sstevel@tonic-gate C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 3657c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) 3667c478bd9Sstevel@tonic-gate { 3677c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 3687c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 3697c478bd9Sstevel@tonic-gate kernel_object_t *new_objp = NULL; 3707c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 3717c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 3727c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj; 3737c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE; 3747c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 3757c478bd9Sstevel@tonic-gate int r; 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate if (!kernel_initialized) 3787c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate /* Obtain the session pointer */ 3817c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 3827c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 3837c478bd9Sstevel@tonic-gate return (rv); 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate if ((pMechanism == NULL) || (phKey == NULL)) { 3867c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 3877c478bd9Sstevel@tonic-gate goto failed_exit; 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate if ((pTemplate == NULL) && (ulCount != 0)) { 3917c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 3927c478bd9Sstevel@tonic-gate goto failed_exit; 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 3967c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 3977c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3987c478bd9Sstevel@tonic-gate goto failed_exit; 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* Create an object wrapper in the library first */ 4027c478bd9Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t)); 4037c478bd9Sstevel@tonic-gate if (new_objp == NULL) { 4047c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 4057c478bd9Sstevel@tonic-gate goto failed_exit; 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate 408*034448feSmcpowers /* 409*034448feSmcpowers * Special Case: if token does not support object creation, 410*034448feSmcpowers * but does support key generation by value, then create a session 411*034448feSmcpowers * object and initialize with value returned by token. 412*034448feSmcpowers */ 413*034448feSmcpowers pslot = slot_table[session_p->ses_slotid]; 414*034448feSmcpowers if (!pslot->sl_func_list.fl_object_create) { 415*034448feSmcpowers rv = key_gen_by_value(pMechanism, pTemplate, ulCount, session_p, 416*034448feSmcpowers k_mech_type, new_objp); 417*034448feSmcpowers if (rv != CKR_OK) 418*034448feSmcpowers goto failed_exit; 419*034448feSmcpowers } else { 420*034448feSmcpowers crypto_object_generate_key_t obj_gk; 421*034448feSmcpowers 4227c478bd9Sstevel@tonic-gate /* Process the attributes */ 4237c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulCount, 4247c478bd9Sstevel@tonic-gate &obj_gk.gk_attributes, &is_token_obj); 4257c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4267c478bd9Sstevel@tonic-gate goto failed_exit; 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */ 4297c478bd9Sstevel@tonic-gate if (is_token_obj && session_p->ses_RO) { 4307c478bd9Sstevel@tonic-gate free_object_attributes(obj_gk.gk_attributes, ulCount); 4317c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY; 4327c478bd9Sstevel@tonic-gate goto failed_exit; 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate /* Call the CRYPTO_GENERATE_KEY ioctl */ 4367c478bd9Sstevel@tonic-gate obj_gk.gk_session = session_p->k_session; 4377c478bd9Sstevel@tonic-gate obj_gk.gk_count = ulCount; 4387c478bd9Sstevel@tonic-gate obj_gk.gk_mechanism.cm_type = k_mech_type; 4397c478bd9Sstevel@tonic-gate obj_gk.gk_mechanism.cm_param = pMechanism->pParameter; 4407c478bd9Sstevel@tonic-gate obj_gk.gk_mechanism.cm_param_len = pMechanism->ulParameterLen; 4417c478bd9Sstevel@tonic-gate 442*034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY, 443*034448feSmcpowers &obj_gk)) < 0) { 4447c478bd9Sstevel@tonic-gate if (errno != EINTR) 4457c478bd9Sstevel@tonic-gate break; 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate if (r < 0) { 4487c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 4497c478bd9Sstevel@tonic-gate } else { 4507c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_gk.gk_return_value); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate free_object_attributes(obj_gk.gk_attributes, ulCount); 454*034448feSmcpowers 4557c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4567c478bd9Sstevel@tonic-gate goto failed_exit; 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate /* Get the value of the CKA_PRIVATE attribute. */ 460*034448feSmcpowers rv = get_cka_private_value(session_p, obj_gk.gk_handle, 461*034448feSmcpowers &is_pri_obj); 4627c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4637c478bd9Sstevel@tonic-gate goto failed_exit; 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate /* 4677c478bd9Sstevel@tonic-gate * Store the kernel object handle in the object wrapper and 4687c478bd9Sstevel@tonic-gate * initialize the library object. 4697c478bd9Sstevel@tonic-gate */ 4707c478bd9Sstevel@tonic-gate new_objp->k_handle = obj_gk.gk_handle; 4717c478bd9Sstevel@tonic-gate new_objp->is_lib_obj = B_FALSE; 4727c478bd9Sstevel@tonic-gate new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 4737c478bd9Sstevel@tonic-gate new_objp->extra_attrlistp = NULL; 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate if (is_pri_obj) 4767c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 4777c478bd9Sstevel@tonic-gate else 4787c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate if (is_token_obj) 4817c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 4827c478bd9Sstevel@tonic-gate else 4837c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 484*034448feSmcpowers } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 4877c478bd9Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate /* 4907c478bd9Sstevel@tonic-gate * Add the new object to the slot's token object list if it is a 4917c478bd9Sstevel@tonic-gate * a token object. Otherwise, add it to the session's object list. 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate if (is_token_obj) { 4947c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 4957c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot); 4967c478bd9Sstevel@tonic-gate } else { 4977c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p); 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp; 5017c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 5027c478bd9Sstevel@tonic-gate return (rv); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate failed_exit: 5057c478bd9Sstevel@tonic-gate if (new_objp != NULL) { 5067c478bd9Sstevel@tonic-gate (void) free(new_objp); 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 5107c478bd9Sstevel@tonic-gate return (rv); 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate 513*034448feSmcpowers CK_RV 514*034448feSmcpowers key_gen_rsa_by_value(CK_MECHANISM_PTR pMechanism, 515*034448feSmcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 516*034448feSmcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 517*034448feSmcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type, 518*034448feSmcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp) 519*034448feSmcpowers { 520*034448feSmcpowers crypto_nostore_generate_key_pair_t obj_nkp; 521*034448feSmcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL; 522*034448feSmcpowers CK_ATTRIBUTE_PTR priTemplate = NULL; 523*034448feSmcpowers CK_RV rv = CKR_OK; 524*034448feSmcpowers CK_BBOOL is_token_obj1 = FALSE; 525*034448feSmcpowers CK_BBOOL is_token_obj2 = FALSE; 526*034448feSmcpowers uint_t pub_attr_count, pri_attr_count; 527*034448feSmcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0; 528*034448feSmcpowers char public_modulus[512]; 529*034448feSmcpowers char public_exponent[8]; 530*034448feSmcpowers char private_exponent[512]; 531*034448feSmcpowers char private_modulus[512]; 532*034448feSmcpowers char prime_1[512]; 533*034448feSmcpowers char prime_2[512]; 534*034448feSmcpowers char exponent_1[512]; 535*034448feSmcpowers char exponent_2[512]; 536*034448feSmcpowers char coefficient[512]; 537*034448feSmcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY; 538*034448feSmcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY; 539*034448feSmcpowers CK_ULONG key_type; 540*034448feSmcpowers CK_ULONG modulus_bytes; 541*034448feSmcpowers boolean_t has_class, has_key_type, has_pub_exponent; 542*034448feSmcpowers int n, r; 543*034448feSmcpowers 544*034448feSmcpowers obj_nkp.nkp_in_public_count = 0; 545*034448feSmcpowers obj_nkp.nkp_out_public_count = 0; 546*034448feSmcpowers obj_nkp.nkp_in_private_count = 0; 547*034448feSmcpowers obj_nkp.nkp_out_private_count = 0; 548*034448feSmcpowers 549*034448feSmcpowers /* modulus bits must be present when generating a RSA key pair */ 550*034448feSmcpowers if (!attribute_in_template(CKA_MODULUS_BITS, pPublicKeyTemplate, 551*034448feSmcpowers ulPublicKeyAttributeCount)) { 552*034448feSmcpowers rv = CKR_TEMPLATE_INCOMPLETE; 553*034448feSmcpowers goto failed_exit; 554*034448feSmcpowers } 555*034448feSmcpowers 556*034448feSmcpowers modulus_bytes = get_modulus_bytes(pPublicKeyTemplate, 557*034448feSmcpowers ulPublicKeyAttributeCount); 558*034448feSmcpowers 559*034448feSmcpowers /* 560*034448feSmcpowers * Add CKA_MODULUS to the public template. 561*034448feSmcpowers * This attribute must not be in the template. 562*034448feSmcpowers */ 563*034448feSmcpowers if (attribute_in_template(CKA_MODULUS, pPublicKeyTemplate, 564*034448feSmcpowers ulPublicKeyAttributeCount)) { 565*034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT; 566*034448feSmcpowers goto failed_exit; 567*034448feSmcpowers } 568*034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate, 569*034448feSmcpowers ulPublicKeyAttributeCount); 570*034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate, 571*034448feSmcpowers ulPublicKeyAttributeCount); 572*034448feSmcpowers has_pub_exponent = attribute_in_template(CKA_PUBLIC_EXPONENT, 573*034448feSmcpowers pPublicKeyTemplate, ulPublicKeyAttributeCount); 574*034448feSmcpowers 575*034448feSmcpowers pub_attr_count = ulPublicKeyAttributeCount + 1; 576*034448feSmcpowers if (!has_class) 577*034448feSmcpowers pub_attr_count++; 578*034448feSmcpowers if (!has_key_type) 579*034448feSmcpowers pub_attr_count++; 580*034448feSmcpowers if (!has_pub_exponent) 581*034448feSmcpowers pub_attr_count++; 582*034448feSmcpowers pubTemplate = grow_template(pPublicKeyTemplate, 583*034448feSmcpowers ulPublicKeyAttributeCount, pub_attr_count); 584*034448feSmcpowers if (pubTemplate == NULL) { 585*034448feSmcpowers rv = CKR_HOST_MEMORY; 586*034448feSmcpowers goto failed_exit; 587*034448feSmcpowers } 588*034448feSmcpowers 589*034448feSmcpowers n = ulPublicKeyAttributeCount; 590*034448feSmcpowers if (!has_class) { 591*034448feSmcpowers pubTemplate[n].type = CKA_CLASS; 592*034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&pub_class; 593*034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (pub_class); 594*034448feSmcpowers n++; 595*034448feSmcpowers } 596*034448feSmcpowers if (!has_key_type) { 597*034448feSmcpowers pubTemplate[n].type = CKA_KEY_TYPE; 598*034448feSmcpowers key_type = CKK_RSA; 599*034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&key_type; 600*034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (key_type); 601*034448feSmcpowers n++; 602*034448feSmcpowers } 603*034448feSmcpowers if (!has_pub_exponent) { 604*034448feSmcpowers pubTemplate[n].type = CKA_PUBLIC_EXPONENT; 605*034448feSmcpowers pubTemplate[n].pValue = (caddr_t)public_exponent; 606*034448feSmcpowers pubTemplate[n].ulValueLen = modulus_bytes; 607*034448feSmcpowers n++; 608*034448feSmcpowers pub_out_attr_count++; 609*034448feSmcpowers } 610*034448feSmcpowers pubTemplate[n].type = CKA_MODULUS; 611*034448feSmcpowers pubTemplate[n].pValue = (caddr_t)public_modulus; 612*034448feSmcpowers pubTemplate[n].ulValueLen = modulus_bytes; 613*034448feSmcpowers pub_out_attr_count++; 614*034448feSmcpowers 615*034448feSmcpowers rv = process_object_attributes(pubTemplate, 616*034448feSmcpowers pub_attr_count - pub_out_attr_count, 617*034448feSmcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1); 618*034448feSmcpowers if (rv != CKR_OK) { 619*034448feSmcpowers goto failed_exit; 620*034448feSmcpowers } 621*034448feSmcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count; 622*034448feSmcpowers 623*034448feSmcpowers rv = process_object_attributes( 624*034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 625*034448feSmcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes, 626*034448feSmcpowers &is_token_obj1); 627*034448feSmcpowers if (rv != CKR_OK) { 628*034448feSmcpowers goto failed_exit; 629*034448feSmcpowers } 630*034448feSmcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count; 631*034448feSmcpowers 632*034448feSmcpowers /* 633*034448feSmcpowers * Cannot create a token object with a READ-ONLY 634*034448feSmcpowers * session. 635*034448feSmcpowers */ 636*034448feSmcpowers if (is_token_obj1 && session_p->ses_RO) { 637*034448feSmcpowers rv = CKR_SESSION_READ_ONLY; 638*034448feSmcpowers goto failed_exit; 639*034448feSmcpowers } 640*034448feSmcpowers 641*034448feSmcpowers /* 642*034448feSmcpowers * Add CKA_MODULUS and CKA_PRIVATE_EXPONENT 643*034448feSmcpowers * to the private template. These attributes 644*034448feSmcpowers * must not be in the template. 645*034448feSmcpowers */ 646*034448feSmcpowers if (attribute_in_template(CKA_PRIVATE_EXPONENT, 647*034448feSmcpowers pPrivateKeyTemplate, ulPrivateKeyAttributeCount) || 648*034448feSmcpowers attribute_in_template(CKA_MODULUS, 649*034448feSmcpowers pPrivateKeyTemplate, ulPrivateKeyAttributeCount)) { 650*034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT; 651*034448feSmcpowers goto failed_exit; 652*034448feSmcpowers } 653*034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate, 654*034448feSmcpowers ulPrivateKeyAttributeCount); 655*034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate, 656*034448feSmcpowers ulPrivateKeyAttributeCount); 657*034448feSmcpowers 658*034448feSmcpowers pri_attr_count = ulPrivateKeyAttributeCount + 7; 659*034448feSmcpowers if (!has_class) 660*034448feSmcpowers pri_attr_count++; 661*034448feSmcpowers if (!has_key_type) 662*034448feSmcpowers pri_attr_count++; 663*034448feSmcpowers 664*034448feSmcpowers /* allocate space for CKA_PUBLIC_EXPONENT */ 665*034448feSmcpowers priTemplate = grow_template(pPrivateKeyTemplate, 666*034448feSmcpowers ulPrivateKeyAttributeCount, pri_attr_count + 1); 667*034448feSmcpowers if (priTemplate == NULL) { 668*034448feSmcpowers rv = CKR_HOST_MEMORY; 669*034448feSmcpowers goto failed_exit; 670*034448feSmcpowers } 671*034448feSmcpowers n = ulPrivateKeyAttributeCount; 672*034448feSmcpowers if (!has_class) { 673*034448feSmcpowers priTemplate[n].type = CKA_CLASS; 674*034448feSmcpowers priTemplate[n].pValue = (caddr_t)&pri_class; 675*034448feSmcpowers priTemplate[n].ulValueLen = sizeof (pri_class); 676*034448feSmcpowers n++; 677*034448feSmcpowers } 678*034448feSmcpowers if (!has_key_type) { 679*034448feSmcpowers priTemplate[n].type = CKA_KEY_TYPE; 680*034448feSmcpowers key_type = CKK_RSA; 681*034448feSmcpowers priTemplate[n].pValue = (caddr_t)&key_type; 682*034448feSmcpowers priTemplate[n].ulValueLen = sizeof (key_type); 683*034448feSmcpowers n++; 684*034448feSmcpowers } 685*034448feSmcpowers priTemplate[n].type = CKA_MODULUS; 686*034448feSmcpowers priTemplate[n].pValue = (caddr_t)private_modulus; 687*034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes; 688*034448feSmcpowers pri_out_attr_count++; 689*034448feSmcpowers 690*034448feSmcpowers n++; 691*034448feSmcpowers priTemplate[n].type = CKA_PRIVATE_EXPONENT; 692*034448feSmcpowers priTemplate[n].pValue = (caddr_t)private_exponent; 693*034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes; 694*034448feSmcpowers pri_out_attr_count++; 695*034448feSmcpowers 696*034448feSmcpowers n++; 697*034448feSmcpowers priTemplate[n].type = CKA_PRIME_1; 698*034448feSmcpowers priTemplate[n].pValue = (caddr_t)prime_1; 699*034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes/2; 700*034448feSmcpowers pri_out_attr_count++; 701*034448feSmcpowers 702*034448feSmcpowers n++; 703*034448feSmcpowers priTemplate[n].type = CKA_PRIME_2; 704*034448feSmcpowers priTemplate[n].pValue = (caddr_t)prime_2; 705*034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes/2; 706*034448feSmcpowers pri_out_attr_count++; 707*034448feSmcpowers 708*034448feSmcpowers n++; 709*034448feSmcpowers priTemplate[n].type = CKA_EXPONENT_1; 710*034448feSmcpowers priTemplate[n].pValue = (caddr_t)exponent_1; 711*034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes/2; 712*034448feSmcpowers pri_out_attr_count++; 713*034448feSmcpowers 714*034448feSmcpowers n++; 715*034448feSmcpowers priTemplate[n].type = CKA_EXPONENT_2; 716*034448feSmcpowers priTemplate[n].pValue = (caddr_t)exponent_2; 717*034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes/2; 718*034448feSmcpowers pri_out_attr_count++; 719*034448feSmcpowers 720*034448feSmcpowers n++; 721*034448feSmcpowers priTemplate[n].type = CKA_COEFFICIENT; 722*034448feSmcpowers priTemplate[n].pValue = (caddr_t)coefficient; 723*034448feSmcpowers priTemplate[n].ulValueLen = modulus_bytes/2; 724*034448feSmcpowers pri_out_attr_count++; 725*034448feSmcpowers 726*034448feSmcpowers rv = process_object_attributes(priTemplate, 727*034448feSmcpowers pri_attr_count - pri_out_attr_count, 728*034448feSmcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2); 729*034448feSmcpowers if (rv != CKR_OK) { 730*034448feSmcpowers goto failed_exit; 731*034448feSmcpowers } 732*034448feSmcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count; 733*034448feSmcpowers 734*034448feSmcpowers rv = process_object_attributes( 735*034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 736*034448feSmcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes, 737*034448feSmcpowers &is_token_obj2); 738*034448feSmcpowers if (rv != CKR_OK) { 739*034448feSmcpowers goto failed_exit; 740*034448feSmcpowers } 741*034448feSmcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count; 742*034448feSmcpowers 743*034448feSmcpowers /* 744*034448feSmcpowers * The public key and the private key need to contain the same 745*034448feSmcpowers * attribute values for CKA_TOKEN. 746*034448feSmcpowers */ 747*034448feSmcpowers if (is_token_obj1 != is_token_obj2) { 748*034448feSmcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID; 749*034448feSmcpowers goto failed_exit; 750*034448feSmcpowers } 751*034448feSmcpowers 752*034448feSmcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */ 753*034448feSmcpowers obj_nkp.nkp_session = session_p-> k_session; 754*034448feSmcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type; 755*034448feSmcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter; 756*034448feSmcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen; 757*034448feSmcpowers 758*034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR, 759*034448feSmcpowers &obj_nkp)) < 0) { 760*034448feSmcpowers if (errno != EINTR) 761*034448feSmcpowers break; 762*034448feSmcpowers } 763*034448feSmcpowers if (r < 0) { 764*034448feSmcpowers rv = CKR_FUNCTION_FAILED; 765*034448feSmcpowers } else { 766*034448feSmcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value); 767*034448feSmcpowers } 768*034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 769*034448feSmcpowers &obj_nkp.nkp_in_public_count); 770*034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 771*034448feSmcpowers &obj_nkp.nkp_in_private_count); 772*034448feSmcpowers 773*034448feSmcpowers if (rv != CKR_OK) { 774*034448feSmcpowers goto failed_exit; 775*034448feSmcpowers } 776*034448feSmcpowers 777*034448feSmcpowers rv = get_object_attributes( 778*034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 779*034448feSmcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes); 780*034448feSmcpowers if (rv == CRYPTO_SUCCESS) { 781*034448feSmcpowers rv = get_object_attributes( 782*034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 783*034448feSmcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes); 784*034448feSmcpowers } 785*034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 786*034448feSmcpowers &obj_nkp.nkp_out_public_count); 787*034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 788*034448feSmcpowers &obj_nkp.nkp_out_private_count); 789*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 790*034448feSmcpowers goto failed_exit; 791*034448feSmcpowers } 792*034448feSmcpowers 793*034448feSmcpowers /* store generated modulus and public exponent */ 794*034448feSmcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp, 795*034448feSmcpowers session_p, KERNEL_GEN_KEY); 796*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 797*034448feSmcpowers goto failed_exit; 798*034448feSmcpowers } 799*034448feSmcpowers 800*034448feSmcpowers /* 801*034448feSmcpowers * Copy CKA_PUBLIC_EXPONENT from the public template 802*034448feSmcpowers * to the private template. 803*034448feSmcpowers */ 804*034448feSmcpowers rv = copy_attribute(CKA_PUBLIC_EXPONENT, pubTemplate, 805*034448feSmcpowers pub_attr_count, &priTemplate[pri_attr_count]); 806*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 807*034448feSmcpowers goto failed_exit; 808*034448feSmcpowers } 809*034448feSmcpowers 810*034448feSmcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 1, new_pri_objp, 811*034448feSmcpowers session_p, KERNEL_GEN_KEY); 812*034448feSmcpowers (void) free(priTemplate[pri_attr_count].pValue); 813*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 814*034448feSmcpowers goto failed_exit; 815*034448feSmcpowers } 816*034448feSmcpowers (void) free(pubTemplate); 817*034448feSmcpowers (void) free(priTemplate); 818*034448feSmcpowers 819*034448feSmcpowers new_pub_objp->is_lib_obj = B_TRUE; 820*034448feSmcpowers new_pri_objp->is_lib_obj = B_TRUE; 821*034448feSmcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 822*034448feSmcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 823*034448feSmcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 824*034448feSmcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 825*034448feSmcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 826*034448feSmcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 827*034448feSmcpowers return (CKR_OK); 828*034448feSmcpowers 829*034448feSmcpowers failed_exit: 830*034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 831*034448feSmcpowers &obj_nkp.nkp_in_public_count); 832*034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 833*034448feSmcpowers &obj_nkp.nkp_out_public_count); 834*034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 835*034448feSmcpowers &obj_nkp.nkp_in_private_count); 836*034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 837*034448feSmcpowers &obj_nkp.nkp_out_private_count); 838*034448feSmcpowers if (pubTemplate != NULL) { 839*034448feSmcpowers (void) free(pubTemplate); 840*034448feSmcpowers } 841*034448feSmcpowers if (priTemplate != NULL) { 842*034448feSmcpowers (void) free(priTemplate); 843*034448feSmcpowers } 844*034448feSmcpowers return (rv); 845*034448feSmcpowers } 846*034448feSmcpowers 847*034448feSmcpowers CK_RV 848*034448feSmcpowers key_gen_dh_by_value(CK_MECHANISM_PTR pMechanism, 849*034448feSmcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 850*034448feSmcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 851*034448feSmcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type, 852*034448feSmcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp) 853*034448feSmcpowers { 854*034448feSmcpowers crypto_nostore_generate_key_pair_t obj_nkp; 855*034448feSmcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL; 856*034448feSmcpowers CK_ATTRIBUTE_PTR priTemplate = NULL; 857*034448feSmcpowers CK_RV rv = CKR_OK; 858*034448feSmcpowers CK_BBOOL is_token_obj1 = FALSE; 859*034448feSmcpowers CK_BBOOL is_token_obj2 = FALSE; 860*034448feSmcpowers uint_t pub_attr_count, pri_attr_count; 861*034448feSmcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0; 862*034448feSmcpowers char public_value[256]; 863*034448feSmcpowers char private_value[256]; 864*034448feSmcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY; 865*034448feSmcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY; 866*034448feSmcpowers CK_ULONG key_type; 867*034448feSmcpowers boolean_t has_class, has_key_type; 868*034448feSmcpowers int n, r; 869*034448feSmcpowers 870*034448feSmcpowers obj_nkp.nkp_in_public_count = 0; 871*034448feSmcpowers obj_nkp.nkp_out_public_count = 0; 872*034448feSmcpowers obj_nkp.nkp_in_private_count = 0; 873*034448feSmcpowers obj_nkp.nkp_out_private_count = 0; 874*034448feSmcpowers 875*034448feSmcpowers /* 876*034448feSmcpowers * Add CKA_VALUE to the public template. 877*034448feSmcpowers * This attribute must not be in the template. 878*034448feSmcpowers */ 879*034448feSmcpowers if (attribute_in_template(CKA_VALUE, pPublicKeyTemplate, 880*034448feSmcpowers ulPublicKeyAttributeCount)) { 881*034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT; 882*034448feSmcpowers goto failed_exit; 883*034448feSmcpowers } 884*034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate, 885*034448feSmcpowers ulPublicKeyAttributeCount); 886*034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate, 887*034448feSmcpowers ulPublicKeyAttributeCount); 888*034448feSmcpowers 889*034448feSmcpowers pub_attr_count = ulPublicKeyAttributeCount + 1; 890*034448feSmcpowers if (!has_class) 891*034448feSmcpowers pub_attr_count++; 892*034448feSmcpowers if (!has_key_type) 893*034448feSmcpowers pub_attr_count++; 894*034448feSmcpowers pubTemplate = grow_template(pPublicKeyTemplate, 895*034448feSmcpowers ulPublicKeyAttributeCount, pub_attr_count); 896*034448feSmcpowers if (pubTemplate == NULL) { 897*034448feSmcpowers rv = CKR_HOST_MEMORY; 898*034448feSmcpowers goto failed_exit; 899*034448feSmcpowers } 900*034448feSmcpowers 901*034448feSmcpowers n = ulPublicKeyAttributeCount; 902*034448feSmcpowers if (!has_class) { 903*034448feSmcpowers pubTemplate[n].type = CKA_CLASS; 904*034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&pub_class; 905*034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (pub_class); 906*034448feSmcpowers n++; 907*034448feSmcpowers } 908*034448feSmcpowers if (!has_key_type) { 909*034448feSmcpowers pubTemplate[n].type = CKA_KEY_TYPE; 910*034448feSmcpowers key_type = CKK_DH; 911*034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&key_type; 912*034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (key_type); 913*034448feSmcpowers n++; 914*034448feSmcpowers } 915*034448feSmcpowers pubTemplate[n].type = CKA_VALUE; 916*034448feSmcpowers pubTemplate[n].pValue = (caddr_t)public_value; 917*034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (public_value); 918*034448feSmcpowers pub_out_attr_count++; 919*034448feSmcpowers 920*034448feSmcpowers rv = process_object_attributes(pubTemplate, 921*034448feSmcpowers pub_attr_count - pub_out_attr_count, 922*034448feSmcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1); 923*034448feSmcpowers if (rv != CKR_OK) { 924*034448feSmcpowers goto failed_exit; 925*034448feSmcpowers } 926*034448feSmcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count; 927*034448feSmcpowers 928*034448feSmcpowers rv = process_object_attributes( 929*034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 930*034448feSmcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes, 931*034448feSmcpowers &is_token_obj1); 932*034448feSmcpowers if (rv != CKR_OK) { 933*034448feSmcpowers goto failed_exit; 934*034448feSmcpowers } 935*034448feSmcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count; 936*034448feSmcpowers 937*034448feSmcpowers /* 938*034448feSmcpowers * Cannot create a token object with a READ-ONLY 939*034448feSmcpowers * session. 940*034448feSmcpowers */ 941*034448feSmcpowers if (is_token_obj1 && session_p->ses_RO) { 942*034448feSmcpowers rv = CKR_SESSION_READ_ONLY; 943*034448feSmcpowers goto failed_exit; 944*034448feSmcpowers } 945*034448feSmcpowers 946*034448feSmcpowers /* 947*034448feSmcpowers * CKA_BASE, CKA_PRIME, and CKA_VALUE must not appear 948*034448feSmcpowers * in private template. 949*034448feSmcpowers */ 950*034448feSmcpowers if (attribute_in_template(CKA_BASE, pPrivateKeyTemplate, 951*034448feSmcpowers ulPrivateKeyAttributeCount) || 952*034448feSmcpowers attribute_in_template(CKA_PRIME, pPrivateKeyTemplate, 953*034448feSmcpowers ulPrivateKeyAttributeCount) || 954*034448feSmcpowers attribute_in_template(CKA_VALUE, pPrivateKeyTemplate, 955*034448feSmcpowers ulPrivateKeyAttributeCount)) { 956*034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT; 957*034448feSmcpowers goto failed_exit; 958*034448feSmcpowers } 959*034448feSmcpowers 960*034448feSmcpowers if (attribute_in_template(CKA_VALUE, pPrivateKeyTemplate, 961*034448feSmcpowers ulPrivateKeyAttributeCount)) { 962*034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT; 963*034448feSmcpowers goto failed_exit; 964*034448feSmcpowers } 965*034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate, 966*034448feSmcpowers ulPrivateKeyAttributeCount); 967*034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate, 968*034448feSmcpowers ulPrivateKeyAttributeCount); 969*034448feSmcpowers 970*034448feSmcpowers pri_attr_count = ulPrivateKeyAttributeCount + 1; 971*034448feSmcpowers if (!has_class) 972*034448feSmcpowers pri_attr_count++; 973*034448feSmcpowers if (!has_key_type) 974*034448feSmcpowers pri_attr_count++; 975*034448feSmcpowers 976*034448feSmcpowers /* allocate space for CKA_BASE and CKA_PRIME */ 977*034448feSmcpowers priTemplate = grow_template(pPrivateKeyTemplate, 978*034448feSmcpowers ulPrivateKeyAttributeCount, pri_attr_count + 2); 979*034448feSmcpowers if (priTemplate == NULL) { 980*034448feSmcpowers rv = CKR_HOST_MEMORY; 981*034448feSmcpowers goto failed_exit; 982*034448feSmcpowers } 983*034448feSmcpowers n = ulPrivateKeyAttributeCount; 984*034448feSmcpowers if (!has_class) { 985*034448feSmcpowers priTemplate[n].type = CKA_CLASS; 986*034448feSmcpowers priTemplate[n].pValue = (caddr_t)&pri_class; 987*034448feSmcpowers priTemplate[n].ulValueLen = sizeof (pri_class); 988*034448feSmcpowers n++; 989*034448feSmcpowers } 990*034448feSmcpowers if (!has_key_type) { 991*034448feSmcpowers priTemplate[n].type = CKA_KEY_TYPE; 992*034448feSmcpowers key_type = CKK_DH; 993*034448feSmcpowers priTemplate[n].pValue = (caddr_t)&key_type; 994*034448feSmcpowers priTemplate[n].ulValueLen = sizeof (key_type); 995*034448feSmcpowers n++; 996*034448feSmcpowers } 997*034448feSmcpowers priTemplate[n].type = CKA_VALUE; 998*034448feSmcpowers priTemplate[n].pValue = (caddr_t)private_value; 999*034448feSmcpowers priTemplate[n].ulValueLen = sizeof (private_value); 1000*034448feSmcpowers pri_out_attr_count++; 1001*034448feSmcpowers 1002*034448feSmcpowers rv = process_object_attributes(priTemplate, 1003*034448feSmcpowers pri_attr_count - pri_out_attr_count, 1004*034448feSmcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2); 1005*034448feSmcpowers if (rv != CKR_OK) { 1006*034448feSmcpowers goto failed_exit; 1007*034448feSmcpowers } 1008*034448feSmcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count; 1009*034448feSmcpowers 1010*034448feSmcpowers rv = process_object_attributes( 1011*034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 1012*034448feSmcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes, 1013*034448feSmcpowers &is_token_obj2); 1014*034448feSmcpowers if (rv != CKR_OK) { 1015*034448feSmcpowers goto failed_exit; 1016*034448feSmcpowers } 1017*034448feSmcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count; 1018*034448feSmcpowers 1019*034448feSmcpowers /* 1020*034448feSmcpowers * The public key and the private key need to contain the same 1021*034448feSmcpowers * attribute values for CKA_TOKEN. 1022*034448feSmcpowers */ 1023*034448feSmcpowers if (is_token_obj1 != is_token_obj2) { 1024*034448feSmcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID; 1025*034448feSmcpowers goto failed_exit; 1026*034448feSmcpowers } 1027*034448feSmcpowers 1028*034448feSmcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */ 1029*034448feSmcpowers obj_nkp.nkp_session = session_p-> k_session; 1030*034448feSmcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type; 1031*034448feSmcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter; 1032*034448feSmcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen; 1033*034448feSmcpowers 1034*034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR, 1035*034448feSmcpowers &obj_nkp)) < 0) { 1036*034448feSmcpowers if (errno != EINTR) 1037*034448feSmcpowers break; 1038*034448feSmcpowers } 1039*034448feSmcpowers if (r < 0) { 1040*034448feSmcpowers rv = CKR_FUNCTION_FAILED; 1041*034448feSmcpowers } else { 1042*034448feSmcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value); 1043*034448feSmcpowers } 1044*034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 1045*034448feSmcpowers &obj_nkp.nkp_in_public_count); 1046*034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 1047*034448feSmcpowers &obj_nkp.nkp_in_private_count); 1048*034448feSmcpowers 1049*034448feSmcpowers if (rv != CKR_OK) { 1050*034448feSmcpowers goto failed_exit; 1051*034448feSmcpowers } 1052*034448feSmcpowers 1053*034448feSmcpowers rv = get_object_attributes( 1054*034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 1055*034448feSmcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes); 1056*034448feSmcpowers if (rv == CRYPTO_SUCCESS) { 1057*034448feSmcpowers rv = get_object_attributes( 1058*034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 1059*034448feSmcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes); 1060*034448feSmcpowers } 1061*034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 1062*034448feSmcpowers &obj_nkp.nkp_out_public_count); 1063*034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 1064*034448feSmcpowers &obj_nkp.nkp_out_private_count); 1065*034448feSmcpowers 1066*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 1067*034448feSmcpowers goto failed_exit; 1068*034448feSmcpowers } 1069*034448feSmcpowers 1070*034448feSmcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp, 1071*034448feSmcpowers session_p, KERNEL_GEN_KEY); 1072*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 1073*034448feSmcpowers goto failed_exit; 1074*034448feSmcpowers } 1075*034448feSmcpowers 1076*034448feSmcpowers /* 1077*034448feSmcpowers * Copy CKA_BASE and CKA_PRIME from the public template 1078*034448feSmcpowers * to the private template. 1079*034448feSmcpowers */ 1080*034448feSmcpowers rv = copy_attribute(CKA_BASE, pubTemplate, pub_attr_count, 1081*034448feSmcpowers &priTemplate[pri_attr_count]); 1082*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 1083*034448feSmcpowers goto failed_exit; 1084*034448feSmcpowers } 1085*034448feSmcpowers rv = copy_attribute(CKA_PRIME, pubTemplate, pub_attr_count, 1086*034448feSmcpowers &priTemplate[pri_attr_count + 1]); 1087*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 1088*034448feSmcpowers (void) free(priTemplate[pri_attr_count].pValue); 1089*034448feSmcpowers goto failed_exit; 1090*034448feSmcpowers } 1091*034448feSmcpowers 1092*034448feSmcpowers /* +2 to account for CKA_BASE and CKA_PRIME */ 1093*034448feSmcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 2, 1094*034448feSmcpowers new_pri_objp, session_p, KERNEL_GEN_KEY); 1095*034448feSmcpowers (void) free(priTemplate[pri_attr_count].pValue); 1096*034448feSmcpowers (void) free(priTemplate[pri_attr_count + 1].pValue); 1097*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 1098*034448feSmcpowers goto failed_exit; 1099*034448feSmcpowers } 1100*034448feSmcpowers (void) free(pubTemplate); 1101*034448feSmcpowers (void) free(priTemplate); 1102*034448feSmcpowers 1103*034448feSmcpowers new_pub_objp->is_lib_obj = B_TRUE; 1104*034448feSmcpowers new_pri_objp->is_lib_obj = B_TRUE; 1105*034448feSmcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1106*034448feSmcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1107*034448feSmcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 1108*034448feSmcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1109*034448feSmcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 1110*034448feSmcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1111*034448feSmcpowers return (CKR_OK); 1112*034448feSmcpowers 1113*034448feSmcpowers failed_exit: 1114*034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 1115*034448feSmcpowers &obj_nkp.nkp_in_public_count); 1116*034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 1117*034448feSmcpowers &obj_nkp.nkp_out_public_count); 1118*034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 1119*034448feSmcpowers &obj_nkp.nkp_in_private_count); 1120*034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 1121*034448feSmcpowers &obj_nkp.nkp_out_private_count); 1122*034448feSmcpowers if (pubTemplate != NULL) { 1123*034448feSmcpowers (void) free(pubTemplate); 1124*034448feSmcpowers } 1125*034448feSmcpowers if (priTemplate != NULL) { 1126*034448feSmcpowers (void) free(priTemplate); 1127*034448feSmcpowers } 1128*034448feSmcpowers return (rv); 1129*034448feSmcpowers } 1130*034448feSmcpowers 1131*034448feSmcpowers CK_RV 1132*034448feSmcpowers key_gen_ec_by_value(CK_MECHANISM_PTR pMechanism, 1133*034448feSmcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 1134*034448feSmcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 1135*034448feSmcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type, 1136*034448feSmcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp) 1137*034448feSmcpowers { 1138*034448feSmcpowers crypto_nostore_generate_key_pair_t obj_nkp; 1139*034448feSmcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL; 1140*034448feSmcpowers CK_ATTRIBUTE_PTR priTemplate = NULL; 1141*034448feSmcpowers CK_RV rv = CKR_OK; 1142*034448feSmcpowers CK_BBOOL is_token_obj1 = FALSE; 1143*034448feSmcpowers CK_BBOOL is_token_obj2 = FALSE; 1144*034448feSmcpowers uint_t pub_attr_count, pri_attr_count; 1145*034448feSmcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0; 1146*034448feSmcpowers char value[32]; 1147*034448feSmcpowers char point[128]; 1148*034448feSmcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY; 1149*034448feSmcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY; 1150*034448feSmcpowers CK_ULONG key_type; 1151*034448feSmcpowers boolean_t has_class, has_key_type; 1152*034448feSmcpowers int n, r; 1153*034448feSmcpowers 1154*034448feSmcpowers obj_nkp.nkp_in_public_count = 0; 1155*034448feSmcpowers obj_nkp.nkp_out_public_count = 0; 1156*034448feSmcpowers obj_nkp.nkp_in_private_count = 0; 1157*034448feSmcpowers obj_nkp.nkp_out_private_count = 0; 1158*034448feSmcpowers 1159*034448feSmcpowers /* 1160*034448feSmcpowers * Add CKA_EC_POINT to the public template. 1161*034448feSmcpowers * This is the generated value Q. This attribute 1162*034448feSmcpowers * must not be in the template. 1163*034448feSmcpowers */ 1164*034448feSmcpowers if (attribute_in_template(CKA_EC_POINT, pPublicKeyTemplate, 1165*034448feSmcpowers ulPublicKeyAttributeCount)) { 1166*034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT; 1167*034448feSmcpowers goto failed_exit; 1168*034448feSmcpowers } 1169*034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate, 1170*034448feSmcpowers ulPublicKeyAttributeCount); 1171*034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate, 1172*034448feSmcpowers ulPublicKeyAttributeCount); 1173*034448feSmcpowers 1174*034448feSmcpowers pub_attr_count = ulPublicKeyAttributeCount + 1; 1175*034448feSmcpowers if (!has_class) 1176*034448feSmcpowers pub_attr_count++; 1177*034448feSmcpowers if (!has_key_type) 1178*034448feSmcpowers pub_attr_count++; 1179*034448feSmcpowers pubTemplate = grow_template(pPublicKeyTemplate, 1180*034448feSmcpowers ulPublicKeyAttributeCount, pub_attr_count); 1181*034448feSmcpowers if (pubTemplate == NULL) { 1182*034448feSmcpowers rv = CKR_HOST_MEMORY; 1183*034448feSmcpowers goto failed_exit; 1184*034448feSmcpowers } 1185*034448feSmcpowers 1186*034448feSmcpowers n = ulPublicKeyAttributeCount; 1187*034448feSmcpowers if (!has_class) { 1188*034448feSmcpowers pubTemplate[n].type = CKA_CLASS; 1189*034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&pub_class; 1190*034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (pub_class); 1191*034448feSmcpowers n++; 1192*034448feSmcpowers } 1193*034448feSmcpowers if (!has_key_type) { 1194*034448feSmcpowers pubTemplate[n].type = CKA_KEY_TYPE; 1195*034448feSmcpowers key_type = CKK_EC; 1196*034448feSmcpowers pubTemplate[n].pValue = (caddr_t)&key_type; 1197*034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (key_type); 1198*034448feSmcpowers n++; 1199*034448feSmcpowers } 1200*034448feSmcpowers pubTemplate[n].type = CKA_EC_POINT; 1201*034448feSmcpowers pubTemplate[n].pValue = (caddr_t)point; 1202*034448feSmcpowers pubTemplate[n].ulValueLen = sizeof (point); 1203*034448feSmcpowers pub_out_attr_count++; 1204*034448feSmcpowers 1205*034448feSmcpowers rv = process_object_attributes(pubTemplate, 1206*034448feSmcpowers pub_attr_count - pub_out_attr_count, 1207*034448feSmcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1); 1208*034448feSmcpowers if (rv != CKR_OK) { 1209*034448feSmcpowers goto failed_exit; 1210*034448feSmcpowers } 1211*034448feSmcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count; 1212*034448feSmcpowers 1213*034448feSmcpowers rv = process_object_attributes( 1214*034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 1215*034448feSmcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes, 1216*034448feSmcpowers &is_token_obj1); 1217*034448feSmcpowers if (rv != CKR_OK) { 1218*034448feSmcpowers goto failed_exit; 1219*034448feSmcpowers } 1220*034448feSmcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count; 1221*034448feSmcpowers 1222*034448feSmcpowers /* 1223*034448feSmcpowers * Cannot create a token object with a READ-ONLY 1224*034448feSmcpowers * session. 1225*034448feSmcpowers */ 1226*034448feSmcpowers if (is_token_obj1 && session_p->ses_RO) { 1227*034448feSmcpowers rv = CKR_SESSION_READ_ONLY; 1228*034448feSmcpowers goto failed_exit; 1229*034448feSmcpowers } 1230*034448feSmcpowers 1231*034448feSmcpowers /* 1232*034448feSmcpowers * CKA_EC_PARAMS and CKA_VALUE must not appear in 1233*034448feSmcpowers * private template. 1234*034448feSmcpowers */ 1235*034448feSmcpowers if (attribute_in_template(CKA_EC_PARAMS, pPrivateKeyTemplate, 1236*034448feSmcpowers ulPrivateKeyAttributeCount) || 1237*034448feSmcpowers attribute_in_template(CKA_VALUE, pPrivateKeyTemplate, 1238*034448feSmcpowers ulPrivateKeyAttributeCount)) { 1239*034448feSmcpowers rv = CKR_TEMPLATE_INCONSISTENT; 1240*034448feSmcpowers goto failed_exit; 1241*034448feSmcpowers } 1242*034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate, 1243*034448feSmcpowers ulPrivateKeyAttributeCount); 1244*034448feSmcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate, 1245*034448feSmcpowers ulPrivateKeyAttributeCount); 1246*034448feSmcpowers 1247*034448feSmcpowers pri_attr_count = ulPrivateKeyAttributeCount + 1; 1248*034448feSmcpowers if (!has_class) 1249*034448feSmcpowers pri_attr_count++; 1250*034448feSmcpowers if (!has_key_type) 1251*034448feSmcpowers pri_attr_count++; 1252*034448feSmcpowers 1253*034448feSmcpowers /* allocate space for CKA_EC_PARAMS */ 1254*034448feSmcpowers priTemplate = grow_template(pPrivateKeyTemplate, 1255*034448feSmcpowers ulPrivateKeyAttributeCount, pri_attr_count + 1); 1256*034448feSmcpowers if (priTemplate == NULL) { 1257*034448feSmcpowers rv = CKR_HOST_MEMORY; 1258*034448feSmcpowers goto failed_exit; 1259*034448feSmcpowers } 1260*034448feSmcpowers n = ulPrivateKeyAttributeCount; 1261*034448feSmcpowers if (!has_class) { 1262*034448feSmcpowers priTemplate[n].type = CKA_CLASS; 1263*034448feSmcpowers priTemplate[n].pValue = (caddr_t)&pri_class; 1264*034448feSmcpowers priTemplate[n].ulValueLen = sizeof (pri_class); 1265*034448feSmcpowers n++; 1266*034448feSmcpowers } 1267*034448feSmcpowers if (!has_key_type) { 1268*034448feSmcpowers priTemplate[n].type = CKA_KEY_TYPE; 1269*034448feSmcpowers key_type = CKK_EC; 1270*034448feSmcpowers priTemplate[n].pValue = (caddr_t)&key_type; 1271*034448feSmcpowers priTemplate[n].ulValueLen = sizeof (key_type); 1272*034448feSmcpowers n++; 1273*034448feSmcpowers } 1274*034448feSmcpowers priTemplate[n].type = CKA_VALUE; 1275*034448feSmcpowers priTemplate[n].pValue = (caddr_t)value; 1276*034448feSmcpowers priTemplate[n].ulValueLen = sizeof (value); 1277*034448feSmcpowers pri_out_attr_count++; 1278*034448feSmcpowers 1279*034448feSmcpowers rv = process_object_attributes(priTemplate, 1280*034448feSmcpowers pri_attr_count - pri_out_attr_count, 1281*034448feSmcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2); 1282*034448feSmcpowers if (rv != CKR_OK) { 1283*034448feSmcpowers goto failed_exit; 1284*034448feSmcpowers } 1285*034448feSmcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count; 1286*034448feSmcpowers 1287*034448feSmcpowers rv = process_object_attributes( 1288*034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 1289*034448feSmcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes, 1290*034448feSmcpowers &is_token_obj2); 1291*034448feSmcpowers if (rv != CKR_OK) { 1292*034448feSmcpowers goto failed_exit; 1293*034448feSmcpowers } 1294*034448feSmcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count; 1295*034448feSmcpowers 1296*034448feSmcpowers /* 1297*034448feSmcpowers * The public key and the private key need to contain the same 1298*034448feSmcpowers * attribute values for CKA_TOKEN. 1299*034448feSmcpowers */ 1300*034448feSmcpowers if (is_token_obj1 != is_token_obj2) { 1301*034448feSmcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID; 1302*034448feSmcpowers goto failed_exit; 1303*034448feSmcpowers } 1304*034448feSmcpowers 1305*034448feSmcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */ 1306*034448feSmcpowers obj_nkp.nkp_session = session_p-> k_session; 1307*034448feSmcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type; 1308*034448feSmcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter; 1309*034448feSmcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen; 1310*034448feSmcpowers 1311*034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR, 1312*034448feSmcpowers &obj_nkp)) < 0) { 1313*034448feSmcpowers if (errno != EINTR) 1314*034448feSmcpowers break; 1315*034448feSmcpowers } 1316*034448feSmcpowers if (r < 0) { 1317*034448feSmcpowers rv = CKR_FUNCTION_FAILED; 1318*034448feSmcpowers } else { 1319*034448feSmcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value); 1320*034448feSmcpowers } 1321*034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 1322*034448feSmcpowers &obj_nkp.nkp_in_public_count); 1323*034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 1324*034448feSmcpowers &obj_nkp.nkp_in_private_count); 1325*034448feSmcpowers 1326*034448feSmcpowers if (rv != CKR_OK) { 1327*034448feSmcpowers goto failed_exit; 1328*034448feSmcpowers } 1329*034448feSmcpowers 1330*034448feSmcpowers rv = get_object_attributes( 1331*034448feSmcpowers &pubTemplate[pub_attr_count - pub_out_attr_count], 1332*034448feSmcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes); 1333*034448feSmcpowers if (rv == CRYPTO_SUCCESS) { 1334*034448feSmcpowers rv = get_object_attributes( 1335*034448feSmcpowers &priTemplate[pri_attr_count - pri_out_attr_count], 1336*034448feSmcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes); 1337*034448feSmcpowers } 1338*034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 1339*034448feSmcpowers &obj_nkp.nkp_out_public_count); 1340*034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 1341*034448feSmcpowers &obj_nkp.nkp_out_private_count); 1342*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 1343*034448feSmcpowers goto failed_exit; 1344*034448feSmcpowers } 1345*034448feSmcpowers 1346*034448feSmcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp, 1347*034448feSmcpowers session_p, KERNEL_GEN_KEY); 1348*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 1349*034448feSmcpowers goto failed_exit; 1350*034448feSmcpowers } 1351*034448feSmcpowers 1352*034448feSmcpowers /* 1353*034448feSmcpowers * Copy CKA_EC_PARAMS from the public template to the 1354*034448feSmcpowers * private template. 1355*034448feSmcpowers */ 1356*034448feSmcpowers rv = copy_attribute(CKA_EC_PARAMS, pubTemplate, pub_attr_count, 1357*034448feSmcpowers &priTemplate[pri_attr_count]); 1358*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 1359*034448feSmcpowers goto failed_exit; 1360*034448feSmcpowers } 1361*034448feSmcpowers 1362*034448feSmcpowers /* +1 to account for CKA_EC_PARAMS */ 1363*034448feSmcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 1, 1364*034448feSmcpowers new_pri_objp, session_p, KERNEL_GEN_KEY); 1365*034448feSmcpowers (void) free(priTemplate[pri_attr_count].pValue); 1366*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 1367*034448feSmcpowers goto failed_exit; 1368*034448feSmcpowers } 1369*034448feSmcpowers (void) free(pubTemplate); 1370*034448feSmcpowers (void) free(priTemplate); 1371*034448feSmcpowers 1372*034448feSmcpowers new_pub_objp->is_lib_obj = B_TRUE; 1373*034448feSmcpowers new_pri_objp->is_lib_obj = B_TRUE; 1374*034448feSmcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1375*034448feSmcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1376*034448feSmcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 1377*034448feSmcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1378*034448feSmcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 1379*034448feSmcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1380*034448feSmcpowers return (CKR_OK); 1381*034448feSmcpowers 1382*034448feSmcpowers failed_exit: 1383*034448feSmcpowers free_attributes(obj_nkp.nkp_in_public_attributes, 1384*034448feSmcpowers &obj_nkp.nkp_in_public_count); 1385*034448feSmcpowers free_attributes(obj_nkp.nkp_out_public_attributes, 1386*034448feSmcpowers &obj_nkp.nkp_out_public_count); 1387*034448feSmcpowers free_attributes(obj_nkp.nkp_in_private_attributes, 1388*034448feSmcpowers &obj_nkp.nkp_in_private_count); 1389*034448feSmcpowers free_attributes(obj_nkp.nkp_out_private_attributes, 1390*034448feSmcpowers &obj_nkp.nkp_out_private_count); 1391*034448feSmcpowers if (pubTemplate != NULL) { 1392*034448feSmcpowers (void) free(pubTemplate); 1393*034448feSmcpowers } 1394*034448feSmcpowers if (priTemplate != NULL) { 1395*034448feSmcpowers (void) free(priTemplate); 1396*034448feSmcpowers } 1397*034448feSmcpowers return (rv); 1398*034448feSmcpowers } 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate CK_RV 14017c478bd9Sstevel@tonic-gate C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 14027c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 14037c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 14047c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) 14057c478bd9Sstevel@tonic-gate { 14067c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 14077c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 14087c478bd9Sstevel@tonic-gate kernel_object_t *new_pub_objp = NULL; 14097c478bd9Sstevel@tonic-gate kernel_object_t *new_pri_objp = NULL; 14107c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 14117c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 14127c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj1; 14137c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj2; 14147c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj1 = FALSE; 14157c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj2 = FALSE; 14167c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 14177c478bd9Sstevel@tonic-gate int r; 1418*034448feSmcpowers CK_RV (*func)(CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, 1419*034448feSmcpowers CK_ATTRIBUTE_PTR, CK_ULONG, kernel_session_t *, crypto_mech_type_t, 1420*034448feSmcpowers kernel_object_t *, kernel_object_t *); 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate if (!kernel_initialized) 14237c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 14267c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 14277c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 14287c478bd9Sstevel@tonic-gate return (rv); 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate if ((pMechanism == NULL) || (phPublicKey == NULL) || 14317c478bd9Sstevel@tonic-gate (phPrivateKey == NULL)) { 14327c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 14337c478bd9Sstevel@tonic-gate goto failed_exit; 14347c478bd9Sstevel@tonic-gate } 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate if ((pPublicKeyTemplate == NULL) && (ulPublicKeyAttributeCount != 0)) { 14377c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 14387c478bd9Sstevel@tonic-gate goto failed_exit; 14397c478bd9Sstevel@tonic-gate } 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate if ((pPrivateKeyTemplate == NULL) && 14427c478bd9Sstevel@tonic-gate (ulPrivateKeyAttributeCount != 0)) { 14437c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 14447c478bd9Sstevel@tonic-gate goto failed_exit; 14457c478bd9Sstevel@tonic-gate } 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 14487c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 14497c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 14507c478bd9Sstevel@tonic-gate goto failed_exit; 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate /* Create an object wrapper for the public key */ 14547c478bd9Sstevel@tonic-gate new_pub_objp = calloc(1, sizeof (kernel_object_t)); 14557c478bd9Sstevel@tonic-gate if (new_pub_objp == NULL) { 14567c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 14577c478bd9Sstevel@tonic-gate goto failed_exit; 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate /* Create an object wrapper for the private key. */ 14617c478bd9Sstevel@tonic-gate new_pri_objp = calloc(1, sizeof (kernel_object_t)); 14627c478bd9Sstevel@tonic-gate if (new_pri_objp == NULL) { 14637c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 14647c478bd9Sstevel@tonic-gate goto failed_exit; 14657c478bd9Sstevel@tonic-gate } 14667c478bd9Sstevel@tonic-gate 1467*034448feSmcpowers /* 1468*034448feSmcpowers * Special Case: if token does not support object creation, 1469*034448feSmcpowers * but does support key generation by value, then create a session 1470*034448feSmcpowers * object and initialize with values returned by token. 1471*034448feSmcpowers */ 1472*034448feSmcpowers pslot = slot_table[session_p->ses_slotid]; 1473*034448feSmcpowers if (!pslot->sl_func_list.fl_object_create) { 1474*034448feSmcpowers switch (pMechanism->mechanism) { 1475*034448feSmcpowers case CKM_RSA_PKCS_KEY_PAIR_GEN: 1476*034448feSmcpowers func = key_gen_rsa_by_value; 1477*034448feSmcpowers break; 1478*034448feSmcpowers 1479*034448feSmcpowers case CKM_DH_PKCS_KEY_PAIR_GEN: 1480*034448feSmcpowers func = key_gen_dh_by_value; 1481*034448feSmcpowers break; 1482*034448feSmcpowers 1483*034448feSmcpowers case CKM_EC_KEY_PAIR_GEN: 1484*034448feSmcpowers func = key_gen_ec_by_value; 1485*034448feSmcpowers break; 1486*034448feSmcpowers 1487*034448feSmcpowers default: 1488*034448feSmcpowers rv = CKR_MECHANISM_INVALID; 1489*034448feSmcpowers goto failed_exit; 1490*034448feSmcpowers } 1491*034448feSmcpowers rv = (*func)(pMechanism, pPublicKeyTemplate, 1492*034448feSmcpowers ulPublicKeyAttributeCount, pPrivateKeyTemplate, 1493*034448feSmcpowers ulPrivateKeyAttributeCount, session_p, k_mech_type, 1494*034448feSmcpowers new_pub_objp, new_pri_objp); 1495*034448feSmcpowers if (rv != CKR_OK) 1496*034448feSmcpowers goto failed_exit; 1497*034448feSmcpowers } else { 1498*034448feSmcpowers crypto_object_generate_key_pair_t obj_kp; 1499*034448feSmcpowers 15007c478bd9Sstevel@tonic-gate /* Process the public key attributes. */ 15017c478bd9Sstevel@tonic-gate rv = process_object_attributes(pPublicKeyTemplate, 15027c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount, &obj_kp.kp_public_attributes, 15037c478bd9Sstevel@tonic-gate &is_token_obj1); 15047c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 15057c478bd9Sstevel@tonic-gate goto failed_exit; 15067c478bd9Sstevel@tonic-gate } 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */ 15097c478bd9Sstevel@tonic-gate if (is_token_obj1 && session_p->ses_RO) { 15107c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes, 15117c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount); 15127c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY; 15137c478bd9Sstevel@tonic-gate goto failed_exit; 15147c478bd9Sstevel@tonic-gate } 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate /* Process the private key attributes. */ 15177c478bd9Sstevel@tonic-gate rv = process_object_attributes(pPrivateKeyTemplate, 15187c478bd9Sstevel@tonic-gate ulPrivateKeyAttributeCount, &obj_kp.kp_private_attributes, 15197c478bd9Sstevel@tonic-gate &is_token_obj2); 15207c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 15217c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes, 15227c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount); 15237c478bd9Sstevel@tonic-gate goto failed_exit; 15247c478bd9Sstevel@tonic-gate } 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate /* 15277c478bd9Sstevel@tonic-gate * The public key and the private key need to contain the same 15287c478bd9Sstevel@tonic-gate * attribute values for CKA_TOKEN. 15297c478bd9Sstevel@tonic-gate */ 15307c478bd9Sstevel@tonic-gate if (is_token_obj1 != is_token_obj2) { 15317c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes, 15327c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount); 15337c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_private_attributes, 15347c478bd9Sstevel@tonic-gate ulPrivateKeyAttributeCount); 15357c478bd9Sstevel@tonic-gate rv = CKR_ATTRIBUTE_VALUE_INVALID; 15367c478bd9Sstevel@tonic-gate goto failed_exit; 15377c478bd9Sstevel@tonic-gate } 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate /* Call the CRYPTO_GENERATE_KEY_PAIR ioctl. */ 15407c478bd9Sstevel@tonic-gate obj_kp.kp_session = session_p-> k_session; 15417c478bd9Sstevel@tonic-gate obj_kp.kp_mechanism.cm_type = k_mech_type; 15427c478bd9Sstevel@tonic-gate obj_kp.kp_mechanism.cm_param = pMechanism->pParameter; 15437c478bd9Sstevel@tonic-gate obj_kp.kp_mechanism.cm_param_len = pMechanism->ulParameterLen; 15447c478bd9Sstevel@tonic-gate obj_kp.kp_public_count = ulPublicKeyAttributeCount; 15457c478bd9Sstevel@tonic-gate obj_kp.kp_private_count = ulPrivateKeyAttributeCount; 15467c478bd9Sstevel@tonic-gate 1547*034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY_PAIR, 1548*034448feSmcpowers &obj_kp)) < 0) { 15497c478bd9Sstevel@tonic-gate if (errno != EINTR) 15507c478bd9Sstevel@tonic-gate break; 15517c478bd9Sstevel@tonic-gate } 15527c478bd9Sstevel@tonic-gate if (r < 0) { 15537c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 15547c478bd9Sstevel@tonic-gate } else { 15557c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_kp.kp_return_value); 15567c478bd9Sstevel@tonic-gate } 15577c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes, 15587c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount); 15597c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_private_attributes, 15607c478bd9Sstevel@tonic-gate ulPrivateKeyAttributeCount); 15617c478bd9Sstevel@tonic-gate 1562*034448feSmcpowers if (rv != CKR_OK) 15637c478bd9Sstevel@tonic-gate goto failed_exit; 15647c478bd9Sstevel@tonic-gate 15657c478bd9Sstevel@tonic-gate /* Get the CKA_PRIVATE value for the key pair. */ 15667c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_kp.kp_public_handle, 15677c478bd9Sstevel@tonic-gate &is_pri_obj1); 15687c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 15697c478bd9Sstevel@tonic-gate goto failed_exit; 15707c478bd9Sstevel@tonic-gate } 15717c478bd9Sstevel@tonic-gate 15727c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_kp.kp_private_handle, 15737c478bd9Sstevel@tonic-gate &is_pri_obj2); 15747c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 15757c478bd9Sstevel@tonic-gate goto failed_exit; 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate /* 1579*034448feSmcpowers * Store the kernel public key handle into the public key 1580*034448feSmcpowers * object and finish the public key object initialization. 15817c478bd9Sstevel@tonic-gate */ 15827c478bd9Sstevel@tonic-gate new_pub_objp->is_lib_obj = B_FALSE; 15837c478bd9Sstevel@tonic-gate new_pub_objp->k_handle = obj_kp.kp_public_handle; 15847c478bd9Sstevel@tonic-gate new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 15857c478bd9Sstevel@tonic-gate new_pub_objp->extra_attrlistp = NULL; 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate if (is_pri_obj1) 15887c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 15897c478bd9Sstevel@tonic-gate else 15907c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate if (is_token_obj1) 15937c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask |= TOKEN_BOOL_ON; 15947c478bd9Sstevel@tonic-gate else 15957c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 15967c478bd9Sstevel@tonic-gate 15977c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 15987c478bd9Sstevel@tonic-gate new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 15997c478bd9Sstevel@tonic-gate 16007c478bd9Sstevel@tonic-gate /* 1601*034448feSmcpowers * Store the kernel private key handle into the private key 1602*034448feSmcpowers * object and finish the private key object initialization. 16037c478bd9Sstevel@tonic-gate */ 16047c478bd9Sstevel@tonic-gate new_pri_objp->is_lib_obj = B_FALSE; 16057c478bd9Sstevel@tonic-gate new_pri_objp->k_handle = obj_kp.kp_private_handle; 16067c478bd9Sstevel@tonic-gate new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 16077c478bd9Sstevel@tonic-gate new_pri_objp->extra_attrlistp = NULL; 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate if (is_pri_obj2) 16107c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 16117c478bd9Sstevel@tonic-gate else 16127c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate if (is_token_obj2) 16157c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask |= TOKEN_BOOL_ON; 16167c478bd9Sstevel@tonic-gate else 16177c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 16187c478bd9Sstevel@tonic-gate 1619*034448feSmcpowers } 16207c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 16217c478bd9Sstevel@tonic-gate new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 16227c478bd9Sstevel@tonic-gate 16237c478bd9Sstevel@tonic-gate /* 16247c478bd9Sstevel@tonic-gate * Add the new pub/pri objects to the slot's token list if they are 16257c478bd9Sstevel@tonic-gate * token objects. Otherwise, add them to the session's object list. 16267c478bd9Sstevel@tonic-gate */ 16277c478bd9Sstevel@tonic-gate if (is_token_obj1) { /* is_token_obj1 == is_token_obj2 */ 16287c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 16297c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_pub_objp, pslot); 16307c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_pri_objp, pslot); 16317c478bd9Sstevel@tonic-gate } else { 16327c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_pub_objp, session_p); 16337c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_pri_objp, session_p); 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate 16367c478bd9Sstevel@tonic-gate *phPublicKey = (CK_OBJECT_HANDLE)new_pub_objp; 16377c478bd9Sstevel@tonic-gate *phPrivateKey = (CK_OBJECT_HANDLE)new_pri_objp; 16387c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 16397c478bd9Sstevel@tonic-gate return (rv); 16407c478bd9Sstevel@tonic-gate 16417c478bd9Sstevel@tonic-gate failed_exit: 16427c478bd9Sstevel@tonic-gate if (new_pub_objp != NULL) { 16437c478bd9Sstevel@tonic-gate (void) free(new_pub_objp); 16447c478bd9Sstevel@tonic-gate } 16457c478bd9Sstevel@tonic-gate if (new_pri_objp != NULL) { 16467c478bd9Sstevel@tonic-gate (void) free(new_pri_objp); 16477c478bd9Sstevel@tonic-gate } 16487c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 16497c478bd9Sstevel@tonic-gate return (rv); 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate CK_RV 16547c478bd9Sstevel@tonic-gate C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 16557c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, 16567c478bd9Sstevel@tonic-gate CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) 16577c478bd9Sstevel@tonic-gate { 16587c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 16597c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 16607c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 16617c478bd9Sstevel@tonic-gate kernel_object_t *wrappingkey_p; 16627c478bd9Sstevel@tonic-gate kernel_object_t *key_p; 16637c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 16647c478bd9Sstevel@tonic-gate crypto_object_wrap_key_t obj_wrapkey; 16657c478bd9Sstevel@tonic-gate int r; 16667c478bd9Sstevel@tonic-gate 16677c478bd9Sstevel@tonic-gate if (!kernel_initialized) 16687c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 16697c478bd9Sstevel@tonic-gate 16707c478bd9Sstevel@tonic-gate if (pulWrappedKeyLen == NULL || pMechanism == NULL) { 16717c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 16727c478bd9Sstevel@tonic-gate } 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate /* 16757c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session 16767c478bd9Sstevel@tonic-gate * reference count. 16777c478bd9Sstevel@tonic-gate */ 16787c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 16797c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 16807c478bd9Sstevel@tonic-gate return (rv); 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 16837c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 16847c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 16857c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 16867c478bd9Sstevel@tonic-gate return (rv); 16877c478bd9Sstevel@tonic-gate } 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate /* Obtain the wrapping key object pointer. */ 16907c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hWrappingKey, wrappingkey_p, rv); 16917c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 16927c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 16937c478bd9Sstevel@tonic-gate return (rv); 16947c478bd9Sstevel@tonic-gate } 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate /* Obtain the to_be_wrapped key object pointer. */ 16977c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hKey, key_p, rv); 16987c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 169901223cbaSmcpowers OBJ_REFRELE(wrappingkey_p); 17007c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 17017c478bd9Sstevel@tonic-gate return (rv); 17027c478bd9Sstevel@tonic-gate } 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate /* Make the CRYPTO_OBJECT_WRAP_KEY ioctl call. */ 17057c478bd9Sstevel@tonic-gate obj_wrapkey.wk_session = session_p->k_session; 17067c478bd9Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_type = k_mech_type; 17077c478bd9Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_param = pMechanism->pParameter; 17087c478bd9Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_param_len = pMechanism->ulParameterLen; 17097c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapping_key.ck_format = CRYPTO_KEY_REFERENCE; 17107c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapping_key.ck_obj_id = wrappingkey_p->k_handle; 17117c478bd9Sstevel@tonic-gate obj_wrapkey.wk_object_handle = key_p->k_handle; 17127c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapped_key_len = *pulWrappedKeyLen; 17137c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapped_key = (char *)pWrappedKey; 17147c478bd9Sstevel@tonic-gate 17157c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_WRAP_KEY, &obj_wrapkey)) < 0) { 17167c478bd9Sstevel@tonic-gate if (errno != EINTR) 17177c478bd9Sstevel@tonic-gate break; 17187c478bd9Sstevel@tonic-gate } 17197c478bd9Sstevel@tonic-gate if (r < 0) { 17207c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 17217c478bd9Sstevel@tonic-gate } else { 17227c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_wrapkey.wk_return_value); 17237c478bd9Sstevel@tonic-gate } 17247c478bd9Sstevel@tonic-gate 17257c478bd9Sstevel@tonic-gate /* 17267c478bd9Sstevel@tonic-gate * Besides rv == CKR_OK, we will set the value of pulWrappedKeyLen 17277c478bd9Sstevel@tonic-gate * when the applciation-supplied wrapped key buffer is too small. 17287c478bd9Sstevel@tonic-gate * The situation that the application only asks for the length of 17297c478bd9Sstevel@tonic-gate * the wrapped key is covered in rv == CKR_OK. 17307c478bd9Sstevel@tonic-gate */ 17317c478bd9Sstevel@tonic-gate if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) { 17327c478bd9Sstevel@tonic-gate *pulWrappedKeyLen = obj_wrapkey.wk_wrapped_key_len; 17337c478bd9Sstevel@tonic-gate } 17347c478bd9Sstevel@tonic-gate 173501223cbaSmcpowers OBJ_REFRELE(key_p); 173601223cbaSmcpowers OBJ_REFRELE(wrappingkey_p); 17377c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 17387c478bd9Sstevel@tonic-gate return (rv); 17397c478bd9Sstevel@tonic-gate } 17407c478bd9Sstevel@tonic-gate 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate CK_RV 17437c478bd9Sstevel@tonic-gate C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 17447c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, 17457c478bd9Sstevel@tonic-gate CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, 17467c478bd9Sstevel@tonic-gate CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) 17477c478bd9Sstevel@tonic-gate { 17487c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 17497c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 17507c478bd9Sstevel@tonic-gate kernel_object_t *unwrappingkey_p; 17517c478bd9Sstevel@tonic-gate kernel_object_t *new_objp = NULL; 17527c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 17537c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 17547c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj; 17557c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE; 17567c478bd9Sstevel@tonic-gate CK_MECHANISM_INFO info; 17577c478bd9Sstevel@tonic-gate uint32_t k_mi_flags; 17587c478bd9Sstevel@tonic-gate CK_BYTE *clear_key_val = NULL; 17597c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen; 17607c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR newTemplate = NULL; 17617c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 17627c478bd9Sstevel@tonic-gate crypto_object_unwrap_key_t obj_unwrapkey; 17637c478bd9Sstevel@tonic-gate int r; 17647c478bd9Sstevel@tonic-gate 17657c478bd9Sstevel@tonic-gate if (!kernel_initialized) 17667c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 17677c478bd9Sstevel@tonic-gate 17687c478bd9Sstevel@tonic-gate if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL) { 17697c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 17707c478bd9Sstevel@tonic-gate } 17717c478bd9Sstevel@tonic-gate 17727c478bd9Sstevel@tonic-gate if ((pTemplate == NULL) && (ulAttributeCount != 0)) { 17737c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 17747c478bd9Sstevel@tonic-gate } 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 17777c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 17787c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 17797c478bd9Sstevel@tonic-gate return (rv); 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate /* Obtain the wrapping key object pointer. */ 17827c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hUnwrappingKey, unwrappingkey_p, rv); 17837c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 178401223cbaSmcpowers REFRELE(session_p, ses_lock_held); 178501223cbaSmcpowers return (rv); 17867c478bd9Sstevel@tonic-gate } 17877c478bd9Sstevel@tonic-gate 17887c478bd9Sstevel@tonic-gate /* 17897c478bd9Sstevel@tonic-gate * If the HW provider doesn't support C_UnwrapKey, we will try 17907c478bd9Sstevel@tonic-gate * to emulate it in the library. 17917c478bd9Sstevel@tonic-gate */ 17927c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 1793*034448feSmcpowers if ((!pslot->sl_func_list.fl_object_create) && 1794*034448feSmcpowers (!pslot->sl_func_list.fl_key_unwrap)) { 17957c478bd9Sstevel@tonic-gate rv = get_mechanism_info(pslot, pMechanism->mechanism, &info, 17967c478bd9Sstevel@tonic-gate &k_mi_flags); 17977c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 17987c478bd9Sstevel@tonic-gate goto failed_exit; 17997c478bd9Sstevel@tonic-gate } 18007c478bd9Sstevel@tonic-gate 18017c478bd9Sstevel@tonic-gate /* 18027c478bd9Sstevel@tonic-gate * If the mechanism flag doesn't have CKF_UNWRAP, and it's 18037c478bd9Sstevel@tonic-gate * an unwrapping of a secret key object, then help this 18047c478bd9Sstevel@tonic-gate * out with a decryption followed by an object creation. 18057c478bd9Sstevel@tonic-gate */ 18067c478bd9Sstevel@tonic-gate if (!(k_mi_flags & CRYPTO_FG_UNWRAP) && 18077c478bd9Sstevel@tonic-gate (k_mi_flags & CRYPTO_FG_DECRYPT) && 18087c478bd9Sstevel@tonic-gate (is_secret_key_template(pTemplate, ulAttributeCount))) { 18097c478bd9Sstevel@tonic-gate 18107c478bd9Sstevel@tonic-gate /* First allocate space for the recovered key value */ 18117c478bd9Sstevel@tonic-gate clear_key_val = malloc(ulWrappedKeyLen); 18127c478bd9Sstevel@tonic-gate if (clear_key_val == NULL) { 18137c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 18147c478bd9Sstevel@tonic-gate goto failed_exit; 18157c478bd9Sstevel@tonic-gate } 18167c478bd9Sstevel@tonic-gate 18177c478bd9Sstevel@tonic-gate rv = kernel_decrypt_init(session_p, unwrappingkey_p, 18187c478bd9Sstevel@tonic-gate pMechanism); 18197c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 18207c478bd9Sstevel@tonic-gate goto failed_exit; 18217c478bd9Sstevel@tonic-gate } 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate ulDataLen = ulWrappedKeyLen; 18247c478bd9Sstevel@tonic-gate rv = kernel_decrypt(session_p, pWrappedKey, 18257c478bd9Sstevel@tonic-gate ulWrappedKeyLen, clear_key_val, &ulDataLen); 18267c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 18277c478bd9Sstevel@tonic-gate goto failed_exit; 18287c478bd9Sstevel@tonic-gate } 18297c478bd9Sstevel@tonic-gate 1830*034448feSmcpowers newTemplate = grow_template(pTemplate, ulAttributeCount, 1831*034448feSmcpowers ulAttributeCount + 1); 18327c478bd9Sstevel@tonic-gate if (newTemplate == NULL) { 18337c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 18347c478bd9Sstevel@tonic-gate goto failed_exit; 18357c478bd9Sstevel@tonic-gate } 1836*034448feSmcpowers /* Now add the CKA_VALUE attribute to template */ 18377c478bd9Sstevel@tonic-gate newTemplate[ulAttributeCount].type = CKA_VALUE; 18387c478bd9Sstevel@tonic-gate newTemplate[ulAttributeCount].pValue = clear_key_val; 18397c478bd9Sstevel@tonic-gate newTemplate[ulAttributeCount].ulValueLen = ulDataLen; 18407c478bd9Sstevel@tonic-gate 18417c478bd9Sstevel@tonic-gate /* Finally create the key, based on the new template */ 18427c478bd9Sstevel@tonic-gate rv = kernel_add_object(newTemplate, 18437c478bd9Sstevel@tonic-gate ulAttributeCount + 1, phKey, session_p); 18447c478bd9Sstevel@tonic-gate (void) free(clear_key_val); 18457c478bd9Sstevel@tonic-gate (void) free(newTemplate); 184601223cbaSmcpowers OBJ_REFRELE(unwrappingkey_p); 18477c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 18487c478bd9Sstevel@tonic-gate return (rv); 18497c478bd9Sstevel@tonic-gate } else { 18507c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 18517c478bd9Sstevel@tonic-gate goto failed_exit; 18527c478bd9Sstevel@tonic-gate } 18537c478bd9Sstevel@tonic-gate } 18547c478bd9Sstevel@tonic-gate 18557c478bd9Sstevel@tonic-gate /* 18567c478bd9Sstevel@tonic-gate * If we come here, the HW provider must have registered the unwrapkey 18577c478bd9Sstevel@tonic-gate * entry. Therefore, the unwrap key will be performed in the HW 18587c478bd9Sstevel@tonic-gate * provider. 18597c478bd9Sstevel@tonic-gate */ 18607c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 18617c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 18627c478bd9Sstevel@tonic-gate goto failed_exit; 18637c478bd9Sstevel@tonic-gate } 18647c478bd9Sstevel@tonic-gate 18657c478bd9Sstevel@tonic-gate /* Create an object wrapper for the new key in the library first */ 18667c478bd9Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t)); 18677c478bd9Sstevel@tonic-gate if (new_objp == NULL) { 18687c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 18697c478bd9Sstevel@tonic-gate goto failed_exit; 18707c478bd9Sstevel@tonic-gate } 18717c478bd9Sstevel@tonic-gate 18727c478bd9Sstevel@tonic-gate /* Process the attributes */ 18737c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulAttributeCount, 18747c478bd9Sstevel@tonic-gate &obj_unwrapkey.uk_attributes, &is_token_obj); 18757c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 18767c478bd9Sstevel@tonic-gate goto failed_exit; 18777c478bd9Sstevel@tonic-gate } 18787c478bd9Sstevel@tonic-gate 18797c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */ 18807c478bd9Sstevel@tonic-gate if (is_token_obj && session_p->ses_RO) { 18817c478bd9Sstevel@tonic-gate free_object_attributes(obj_unwrapkey.uk_attributes, 18827c478bd9Sstevel@tonic-gate ulAttributeCount); 18837c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY; 18847c478bd9Sstevel@tonic-gate goto failed_exit; 18857c478bd9Sstevel@tonic-gate } 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate /* Make the CRYPTO_UNWRAP_KEY ioctl call. */ 18887c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_session = session_p->k_session; 18897c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_type = k_mech_type; 18907c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_param = pMechanism->pParameter; 18917c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_param_len = pMechanism->ulParameterLen; 18927c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_unwrapping_key.ck_format = CRYPTO_KEY_REFERENCE; 18937c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_unwrapping_key.ck_obj_id = unwrappingkey_p->k_handle; 18947c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_wrapped_key = (char *)pWrappedKey; 18957c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_wrapped_key_len = ulWrappedKeyLen; 18967c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_count = ulAttributeCount; 18977c478bd9Sstevel@tonic-gate 18987c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_UNWRAP_KEY, &obj_unwrapkey)) < 0) { 18997c478bd9Sstevel@tonic-gate if (errno != EINTR) 19007c478bd9Sstevel@tonic-gate break; 19017c478bd9Sstevel@tonic-gate } 19027c478bd9Sstevel@tonic-gate if (r < 0) { 19037c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 19047c478bd9Sstevel@tonic-gate } else { 19057c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_unwrapkey.uk_return_value); 19067c478bd9Sstevel@tonic-gate } 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate free_object_attributes(obj_unwrapkey.uk_attributes, ulAttributeCount); 19097c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 19107c478bd9Sstevel@tonic-gate goto failed_exit; 19117c478bd9Sstevel@tonic-gate } 19127c478bd9Sstevel@tonic-gate 19137c478bd9Sstevel@tonic-gate /* Get the CKA_PRIVATE value for the unwrapped key. */ 19147c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_unwrapkey.uk_object_handle, 19157c478bd9Sstevel@tonic-gate &is_pri_obj); 19167c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 19177c478bd9Sstevel@tonic-gate goto failed_exit; 19187c478bd9Sstevel@tonic-gate } 19197c478bd9Sstevel@tonic-gate 19207c478bd9Sstevel@tonic-gate /* 19217c478bd9Sstevel@tonic-gate * Store the kernel object handle in the new key object wrapper and 19227c478bd9Sstevel@tonic-gate * initialize it. 19237c478bd9Sstevel@tonic-gate */ 19247c478bd9Sstevel@tonic-gate new_objp->k_handle = obj_unwrapkey.uk_object_handle; 19257c478bd9Sstevel@tonic-gate new_objp->is_lib_obj = B_FALSE; 19267c478bd9Sstevel@tonic-gate new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 19277c478bd9Sstevel@tonic-gate new_objp->extra_attrlistp = NULL; 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate if (is_pri_obj) 19307c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 19317c478bd9Sstevel@tonic-gate else 19327c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 19337c478bd9Sstevel@tonic-gate 19347c478bd9Sstevel@tonic-gate if (is_token_obj) 19357c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 19367c478bd9Sstevel@tonic-gate else 19377c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 19387c478bd9Sstevel@tonic-gate 19397c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 19407c478bd9Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate /* 19437c478bd9Sstevel@tonic-gate * Add the new object to the slot's token object list if it is a 19447c478bd9Sstevel@tonic-gate * a token object. Otherwise, add it to the session's object list. 19457c478bd9Sstevel@tonic-gate */ 19467c478bd9Sstevel@tonic-gate if (is_token_obj) { 19477c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 19487c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot); 19497c478bd9Sstevel@tonic-gate } else { 19507c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p); 19517c478bd9Sstevel@tonic-gate } 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp; 195401223cbaSmcpowers OBJ_REFRELE(unwrappingkey_p); 19557c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 19567c478bd9Sstevel@tonic-gate return (rv); 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate failed_exit: 195901223cbaSmcpowers OBJ_REFRELE(unwrappingkey_p); 19607c478bd9Sstevel@tonic-gate if (new_objp != NULL) 19617c478bd9Sstevel@tonic-gate (void) free(new_objp); 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate if (clear_key_val != NULL) 19647c478bd9Sstevel@tonic-gate (void) free(clear_key_val); 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate if (newTemplate != NULL) 19677c478bd9Sstevel@tonic-gate (void) free(newTemplate); 19687c478bd9Sstevel@tonic-gate 19697c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 19707c478bd9Sstevel@tonic-gate return (rv); 19717c478bd9Sstevel@tonic-gate } 19727c478bd9Sstevel@tonic-gate 1973*034448feSmcpowers /* 1974*034448feSmcpowers * Get sufficient attributes from a base key to pass by value in a 1975*034448feSmcpowers * crypto_key structure. Storage for attributes is allocated. 1976*034448feSmcpowers * For EC public keys, it is CKA_EC_PARAMS and CKA_EC_POINT. 1977*034448feSmcpowers * For EC private keys, it is CKA_EC_PARAMS and CKA_VALUE. 1978*034448feSmcpowers */ 1979*034448feSmcpowers static int 1980*034448feSmcpowers get_base_key_attributes(kernel_object_t *base_key, crypto_key_t *key_by_value) 1981*034448feSmcpowers { 1982*034448feSmcpowers CK_ATTRIBUTE tmp; 1983*034448feSmcpowers crypto_object_attribute_t *attrs; 1984*034448feSmcpowers biginteger_t *big; 1985*034448feSmcpowers int rv; 1986*034448feSmcpowers 1987*034448feSmcpowers switch (base_key->key_type) { 1988*034448feSmcpowers case CKK_EC: 1989*034448feSmcpowers attrs = malloc(2 * sizeof (crypto_object_attribute_t)); 1990*034448feSmcpowers if (attrs == NULL) { 1991*034448feSmcpowers rv = CKR_HOST_MEMORY; 1992*034448feSmcpowers goto out; 1993*034448feSmcpowers } 1994*034448feSmcpowers bzero(attrs, 2 * sizeof (crypto_object_attribute_t)); 1995*034448feSmcpowers 1996*034448feSmcpowers (void) pthread_mutex_lock(&base_key->object_mutex); 1997*034448feSmcpowers 1998*034448feSmcpowers if (!base_key->is_lib_obj) { 1999*034448feSmcpowers rv = CRYPTO_ARGUMENTS_BAD; 2000*034448feSmcpowers goto out; 2001*034448feSmcpowers } 2002*034448feSmcpowers 2003*034448feSmcpowers if (base_key->class != CKO_PUBLIC_KEY && 2004*034448feSmcpowers base_key->class != CKO_PRIVATE_KEY) { 2005*034448feSmcpowers rv = CRYPTO_ARGUMENTS_BAD; 2006*034448feSmcpowers goto out; 2007*034448feSmcpowers } 2008*034448feSmcpowers 2009*034448feSmcpowers /* 2010*034448feSmcpowers * Both public and private EC keys should have 2011*034448feSmcpowers * a CKA_EC_PARAMS attribute. 2012*034448feSmcpowers */ 2013*034448feSmcpowers tmp.type = CKA_EC_PARAMS; 2014*034448feSmcpowers tmp.pValue = NULL; 2015*034448feSmcpowers 2016*034448feSmcpowers /* get size of attribute */ 2017*034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp); 2018*034448feSmcpowers if (rv != CKR_OK) { 2019*034448feSmcpowers goto out; 2020*034448feSmcpowers } 2021*034448feSmcpowers 2022*034448feSmcpowers tmp.pValue = malloc(tmp.ulValueLen); 2023*034448feSmcpowers if (tmp.pValue == NULL) { 2024*034448feSmcpowers rv = CKR_HOST_MEMORY; 2025*034448feSmcpowers goto out; 2026*034448feSmcpowers } 2027*034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp); 2028*034448feSmcpowers if (rv != CKR_OK) { 2029*034448feSmcpowers goto out; 2030*034448feSmcpowers } 2031*034448feSmcpowers attrs[0].oa_type = tmp.type; 2032*034448feSmcpowers attrs[0].oa_value = tmp.pValue; 2033*034448feSmcpowers attrs[0].oa_value_len = tmp.ulValueLen; 2034*034448feSmcpowers 2035*034448feSmcpowers switch (base_key->class) { 2036*034448feSmcpowers case CKO_PUBLIC_KEY: 2037*034448feSmcpowers big = OBJ_PUB_EC_POINT(base_key); 2038*034448feSmcpowers tmp.type = CKA_EC_POINT; 2039*034448feSmcpowers break; 2040*034448feSmcpowers 2041*034448feSmcpowers case CKO_PRIVATE_KEY: 2042*034448feSmcpowers big = OBJ_PRI_EC_VALUE(base_key); 2043*034448feSmcpowers tmp.type = CKA_VALUE; 2044*034448feSmcpowers break; 2045*034448feSmcpowers 2046*034448feSmcpowers default: 2047*034448feSmcpowers rv = CKR_ATTRIBUTE_TYPE_INVALID; 2048*034448feSmcpowers goto out; 2049*034448feSmcpowers } 2050*034448feSmcpowers tmp.ulValueLen = big->big_value_len; 2051*034448feSmcpowers tmp.pValue = malloc(tmp.ulValueLen); 2052*034448feSmcpowers if (tmp.pValue == NULL) { 2053*034448feSmcpowers rv = CKR_HOST_MEMORY; 2054*034448feSmcpowers goto out; 2055*034448feSmcpowers } 2056*034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp); 2057*034448feSmcpowers if (rv != CKR_OK) { 2058*034448feSmcpowers goto out; 2059*034448feSmcpowers } 2060*034448feSmcpowers attrs[1].oa_type = tmp.type; 2061*034448feSmcpowers attrs[1].oa_value = tmp.pValue; 2062*034448feSmcpowers attrs[1].oa_value_len = tmp.ulValueLen; 2063*034448feSmcpowers key_by_value->ck_attrs = attrs; 2064*034448feSmcpowers key_by_value->ck_count = 2; 2065*034448feSmcpowers break; 2066*034448feSmcpowers 2067*034448feSmcpowers case CKK_DH: 2068*034448feSmcpowers attrs = malloc(3 * sizeof (crypto_object_attribute_t)); 2069*034448feSmcpowers if (attrs == NULL) { 2070*034448feSmcpowers rv = CKR_HOST_MEMORY; 2071*034448feSmcpowers goto out; 2072*034448feSmcpowers } 2073*034448feSmcpowers bzero(attrs, 3 * sizeof (crypto_object_attribute_t)); 2074*034448feSmcpowers 2075*034448feSmcpowers (void) pthread_mutex_lock(&base_key->object_mutex); 2076*034448feSmcpowers 2077*034448feSmcpowers if (!base_key->is_lib_obj) { 2078*034448feSmcpowers rv = CRYPTO_ARGUMENTS_BAD; 2079*034448feSmcpowers goto out; 2080*034448feSmcpowers } 2081*034448feSmcpowers 2082*034448feSmcpowers if (base_key->class != CKO_PRIVATE_KEY) { 2083*034448feSmcpowers rv = CRYPTO_ARGUMENTS_BAD; 2084*034448feSmcpowers goto out; 2085*034448feSmcpowers } 2086*034448feSmcpowers tmp.type = CKA_BASE; 2087*034448feSmcpowers tmp.pValue = NULL; 2088*034448feSmcpowers 2089*034448feSmcpowers /* get size of attribute */ 2090*034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp); 2091*034448feSmcpowers if (rv != CKR_OK) { 2092*034448feSmcpowers goto out; 2093*034448feSmcpowers } 2094*034448feSmcpowers 2095*034448feSmcpowers tmp.pValue = malloc(tmp.ulValueLen); 2096*034448feSmcpowers if (tmp.pValue == NULL) { 2097*034448feSmcpowers rv = CKR_HOST_MEMORY; 2098*034448feSmcpowers goto out; 2099*034448feSmcpowers } 2100*034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp); 2101*034448feSmcpowers if (rv != CKR_OK) { 2102*034448feSmcpowers goto out; 2103*034448feSmcpowers } 2104*034448feSmcpowers attrs[0].oa_type = tmp.type; 2105*034448feSmcpowers attrs[0].oa_value = tmp.pValue; 2106*034448feSmcpowers attrs[0].oa_value_len = tmp.ulValueLen; 2107*034448feSmcpowers 2108*034448feSmcpowers tmp.type = CKA_PRIME; 2109*034448feSmcpowers tmp.pValue = NULL; 2110*034448feSmcpowers 2111*034448feSmcpowers /* get size of attribute */ 2112*034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp); 2113*034448feSmcpowers if (rv != CKR_OK) { 2114*034448feSmcpowers goto out; 2115*034448feSmcpowers } 2116*034448feSmcpowers 2117*034448feSmcpowers tmp.pValue = malloc(tmp.ulValueLen); 2118*034448feSmcpowers if (tmp.pValue == NULL) { 2119*034448feSmcpowers rv = CKR_HOST_MEMORY; 2120*034448feSmcpowers goto out; 2121*034448feSmcpowers } 2122*034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp); 2123*034448feSmcpowers if (rv != CKR_OK) { 2124*034448feSmcpowers goto out; 2125*034448feSmcpowers } 2126*034448feSmcpowers attrs[1].oa_type = tmp.type; 2127*034448feSmcpowers attrs[1].oa_value = tmp.pValue; 2128*034448feSmcpowers attrs[1].oa_value_len = tmp.ulValueLen; 2129*034448feSmcpowers 2130*034448feSmcpowers big = OBJ_PRI_EC_VALUE(base_key); 2131*034448feSmcpowers tmp.type = CKA_VALUE; 2132*034448feSmcpowers 2133*034448feSmcpowers tmp.ulValueLen = big->big_value_len; 2134*034448feSmcpowers tmp.pValue = malloc(tmp.ulValueLen); 2135*034448feSmcpowers if (tmp.pValue == NULL) { 2136*034448feSmcpowers rv = CKR_HOST_MEMORY; 2137*034448feSmcpowers goto out; 2138*034448feSmcpowers } 2139*034448feSmcpowers rv = kernel_get_attribute(base_key, &tmp); 2140*034448feSmcpowers if (rv != CKR_OK) { 2141*034448feSmcpowers goto out; 2142*034448feSmcpowers } 2143*034448feSmcpowers attrs[2].oa_type = tmp.type; 2144*034448feSmcpowers attrs[2].oa_value = tmp.pValue; 2145*034448feSmcpowers attrs[2].oa_value_len = tmp.ulValueLen; 2146*034448feSmcpowers key_by_value->ck_attrs = attrs; 2147*034448feSmcpowers key_by_value->ck_count = 3; 2148*034448feSmcpowers break; 2149*034448feSmcpowers 2150*034448feSmcpowers default: 2151*034448feSmcpowers rv = CKR_ATTRIBUTE_TYPE_INVALID; 2152*034448feSmcpowers goto out; 2153*034448feSmcpowers } 2154*034448feSmcpowers (void) pthread_mutex_unlock(&base_key->object_mutex); 2155*034448feSmcpowers return (CKR_OK); 2156*034448feSmcpowers 2157*034448feSmcpowers out: 2158*034448feSmcpowers (void) pthread_mutex_unlock(&base_key->object_mutex); 2159*034448feSmcpowers return (rv); 2160*034448feSmcpowers } 2161*034448feSmcpowers 2162*034448feSmcpowers CK_RV 2163*034448feSmcpowers derive_key_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, 2164*034448feSmcpowers CK_ULONG ulAttributeCount, kernel_session_t *session_p, 2165*034448feSmcpowers crypto_mech_type_t k_mech_type, kernel_object_t *basekey_p, 2166*034448feSmcpowers kernel_object_t *new_objp) 2167*034448feSmcpowers { 2168*034448feSmcpowers crypto_nostore_derive_key_t obj_ndk; 2169*034448feSmcpowers char *key_buf = NULL; 2170*034448feSmcpowers CK_ATTRIBUTE_PTR newTemplate = NULL; 2171*034448feSmcpowers CK_BBOOL is_token_obj = FALSE; 2172*034448feSmcpowers CK_RV rv = CKR_OK; 2173*034448feSmcpowers CK_ULONG secret_class = CKO_SECRET_KEY; 2174*034448feSmcpowers ulong_t key_len = 0; 2175*034448feSmcpowers uint_t attr_count = 0; 2176*034448feSmcpowers boolean_t removed; 2177*034448feSmcpowers boolean_t has_class; 2178*034448feSmcpowers int r, n; 2179*034448feSmcpowers 2180*034448feSmcpowers obj_ndk.ndk_in_count = 0; 2181*034448feSmcpowers obj_ndk.ndk_out_count = 0; 2182*034448feSmcpowers obj_ndk.ndk_base_key.ck_count = 0; 2183*034448feSmcpowers 2184*034448feSmcpowers rv = get_key_len_from_template(pMechanism, pTemplate, ulAttributeCount, 2185*034448feSmcpowers basekey_p, &key_len); 2186*034448feSmcpowers if (rv != CKR_OK) { 2187*034448feSmcpowers goto failed_exit; 2188*034448feSmcpowers } 2189*034448feSmcpowers 2190*034448feSmcpowers if ((key_buf = malloc(key_len)) == NULL) { 2191*034448feSmcpowers rv = CKR_HOST_MEMORY; 2192*034448feSmcpowers goto failed_exit; 2193*034448feSmcpowers } 2194*034448feSmcpowers 2195*034448feSmcpowers has_class = attribute_in_template(CKA_CLASS, pTemplate, 2196*034448feSmcpowers ulAttributeCount); 2197*034448feSmcpowers 2198*034448feSmcpowers attr_count = ulAttributeCount + 1; 2199*034448feSmcpowers if (!has_class) 2200*034448feSmcpowers attr_count++; 2201*034448feSmcpowers 2202*034448feSmcpowers newTemplate = grow_template(pTemplate, ulAttributeCount, attr_count); 2203*034448feSmcpowers if (newTemplate == NULL) { 2204*034448feSmcpowers rv = CKR_HOST_MEMORY; 2205*034448feSmcpowers goto failed_exit; 2206*034448feSmcpowers } 2207*034448feSmcpowers 2208*034448feSmcpowers n = ulAttributeCount; 2209*034448feSmcpowers if (!has_class) { 2210*034448feSmcpowers newTemplate[n].type = CKA_CLASS; 2211*034448feSmcpowers newTemplate[n].pValue = (caddr_t)&secret_class; 2212*034448feSmcpowers newTemplate[n].ulValueLen = sizeof (secret_class); 2213*034448feSmcpowers n++; 2214*034448feSmcpowers } 2215*034448feSmcpowers 2216*034448feSmcpowers /* Add CKA_VALUE to the template */ 2217*034448feSmcpowers newTemplate[n].type = CKA_VALUE; 2218*034448feSmcpowers newTemplate[n].pValue = (caddr_t)key_buf; 2219*034448feSmcpowers newTemplate[n].ulValueLen = key_len; 2220*034448feSmcpowers 2221*034448feSmcpowers rv = process_object_attributes(newTemplate, attr_count - 1, 2222*034448feSmcpowers &obj_ndk.ndk_in_attributes, &is_token_obj); 2223*034448feSmcpowers if (rv != CKR_OK) { 2224*034448feSmcpowers goto failed_exit; 2225*034448feSmcpowers } 2226*034448feSmcpowers 2227*034448feSmcpowers rv = process_object_attributes(&newTemplate[attr_count - 1], 2228*034448feSmcpowers 1, &obj_ndk.ndk_out_attributes, &is_token_obj); 2229*034448feSmcpowers if (rv != CKR_OK) { 2230*034448feSmcpowers goto failed_exit; 2231*034448feSmcpowers } 2232*034448feSmcpowers 2233*034448feSmcpowers /* Cannot create a token object with a READ-ONLY session. */ 2234*034448feSmcpowers if (is_token_obj && session_p->ses_RO) { 2235*034448feSmcpowers rv = CKR_SESSION_READ_ONLY; 2236*034448feSmcpowers goto failed_exit; 2237*034448feSmcpowers } 2238*034448feSmcpowers 2239*034448feSmcpowers obj_ndk.ndk_session = session_p->k_session; 2240*034448feSmcpowers obj_ndk.ndk_mechanism.cm_type = k_mech_type; 2241*034448feSmcpowers obj_ndk.ndk_mechanism.cm_param = pMechanism->pParameter; 2242*034448feSmcpowers obj_ndk.ndk_mechanism.cm_param_len = pMechanism->ulParameterLen; 2243*034448feSmcpowers 2244*034448feSmcpowers /* 2245*034448feSmcpowers * Obtain the attributes of base key and pass them by value. 2246*034448feSmcpowers */ 2247*034448feSmcpowers rv = get_base_key_attributes(basekey_p, &obj_ndk.ndk_base_key); 2248*034448feSmcpowers if (rv != CKR_OK) { 2249*034448feSmcpowers goto failed_exit; 2250*034448feSmcpowers } 2251*034448feSmcpowers 2252*034448feSmcpowers obj_ndk.ndk_base_key.ck_format = CRYPTO_KEY_ATTR_LIST; 2253*034448feSmcpowers obj_ndk.ndk_in_count = attr_count - 1; 2254*034448feSmcpowers obj_ndk.ndk_out_count = 1; 2255*034448feSmcpowers 2256*034448feSmcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_DERIVE_KEY, 2257*034448feSmcpowers &obj_ndk)) < 0) { 2258*034448feSmcpowers if (errno != EINTR) 2259*034448feSmcpowers break; 2260*034448feSmcpowers } 2261*034448feSmcpowers if (r < 0) { 2262*034448feSmcpowers rv = CKR_FUNCTION_FAILED; 2263*034448feSmcpowers } else { 2264*034448feSmcpowers rv = crypto2pkcs11_error_number(obj_ndk.ndk_return_value); 2265*034448feSmcpowers } 2266*034448feSmcpowers free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count); 2267*034448feSmcpowers free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs, 2268*034448feSmcpowers &obj_ndk.ndk_base_key.ck_count); 2269*034448feSmcpowers if (rv != CKR_OK) { 2270*034448feSmcpowers goto failed_exit; 2271*034448feSmcpowers } 2272*034448feSmcpowers 2273*034448feSmcpowers rv = get_object_attributes(&newTemplate[attr_count - 1], 2274*034448feSmcpowers 1, obj_ndk.ndk_out_attributes); 2275*034448feSmcpowers free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count); 2276*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 2277*034448feSmcpowers goto failed_exit; 2278*034448feSmcpowers } 2279*034448feSmcpowers 2280*034448feSmcpowers removed = remove_one_attribute(newTemplate, CKA_VALUE_LEN, 2281*034448feSmcpowers attr_count, B_FALSE); 2282*034448feSmcpowers 2283*034448feSmcpowers rv = kernel_build_object(newTemplate, removed ? attr_count - 1 : 2284*034448feSmcpowers attr_count, new_objp, session_p, KERNEL_GEN_KEY); 2285*034448feSmcpowers if (rv != CRYPTO_SUCCESS) { 2286*034448feSmcpowers goto failed_exit; 2287*034448feSmcpowers } 2288*034448feSmcpowers 2289*034448feSmcpowers free(key_buf); 2290*034448feSmcpowers free(newTemplate); 2291*034448feSmcpowers new_objp->is_lib_obj = B_TRUE; 2292*034448feSmcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 2293*034448feSmcpowers return (CKR_OK); 2294*034448feSmcpowers 2295*034448feSmcpowers failed_exit: 2296*034448feSmcpowers if (key_buf != NULL) 2297*034448feSmcpowers free(key_buf); 2298*034448feSmcpowers if (newTemplate != NULL) 2299*034448feSmcpowers free(newTemplate); 2300*034448feSmcpowers free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count); 2301*034448feSmcpowers free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count); 2302*034448feSmcpowers free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs, 2303*034448feSmcpowers &obj_ndk.ndk_base_key.ck_count); 2304*034448feSmcpowers return (rv); 2305*034448feSmcpowers } 23067c478bd9Sstevel@tonic-gate 23077c478bd9Sstevel@tonic-gate CK_RV 23087c478bd9Sstevel@tonic-gate C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 23097c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, 23107c478bd9Sstevel@tonic-gate CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) 23117c478bd9Sstevel@tonic-gate { 23127c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 23137c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 23147c478bd9Sstevel@tonic-gate kernel_object_t *basekey_p; 23157c478bd9Sstevel@tonic-gate kernel_object_t *new_objp; 23167c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 23177c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 23187c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj; 23197c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE; 23207c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 23217c478bd9Sstevel@tonic-gate int r; 23227c478bd9Sstevel@tonic-gate 23237c478bd9Sstevel@tonic-gate if (!kernel_initialized) 23247c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 23257c478bd9Sstevel@tonic-gate 23267c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 23277c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 23287c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 23297c478bd9Sstevel@tonic-gate return (rv); 23307c478bd9Sstevel@tonic-gate 233160722cc8Sizick if (pMechanism == NULL) { 233201223cbaSmcpowers REFRELE(session_p, ses_lock_held); 233301223cbaSmcpowers return (CKR_ARGUMENTS_BAD); 23347c478bd9Sstevel@tonic-gate } 23357c478bd9Sstevel@tonic-gate 23367c478bd9Sstevel@tonic-gate if ((pTemplate == NULL && ulAttributeCount != 0) || 23377c478bd9Sstevel@tonic-gate (pTemplate != NULL && ulAttributeCount == 0)) { 233801223cbaSmcpowers REFRELE(session_p, ses_lock_held); 233901223cbaSmcpowers return (CKR_ARGUMENTS_BAD); 23407c478bd9Sstevel@tonic-gate } 23417c478bd9Sstevel@tonic-gate 23427c478bd9Sstevel@tonic-gate /* Obtain the base key object pointer. */ 23437c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hBaseKey, basekey_p, rv); 23447c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 234501223cbaSmcpowers REFRELE(session_p, ses_lock_held); 234601223cbaSmcpowers return (rv); 23477c478bd9Sstevel@tonic-gate } 23487c478bd9Sstevel@tonic-gate 23497c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 23507c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 23517c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 23527c478bd9Sstevel@tonic-gate goto failed_exit; 23537c478bd9Sstevel@tonic-gate } 23547c478bd9Sstevel@tonic-gate 23557c478bd9Sstevel@tonic-gate /* Create an object wrapper in the library for the generated key. */ 23567c478bd9Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t)); 23577c478bd9Sstevel@tonic-gate if (new_objp == NULL) { 23587c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 23597c478bd9Sstevel@tonic-gate goto failed_exit; 23607c478bd9Sstevel@tonic-gate } 23617c478bd9Sstevel@tonic-gate 2362*034448feSmcpowers /* 2363*034448feSmcpowers * Special Case: if token does not support object creation, 2364*034448feSmcpowers * but does support key derivation by value, then create a session 2365*034448feSmcpowers * object and initialize with values returned by token. 2366*034448feSmcpowers */ 2367*034448feSmcpowers pslot = slot_table[session_p->ses_slotid]; 2368*034448feSmcpowers if (!pslot->sl_func_list.fl_object_create) { 2369*034448feSmcpowers rv = derive_key_by_value(pMechanism, pTemplate, 2370*034448feSmcpowers ulAttributeCount, session_p, k_mech_type, basekey_p, 2371*034448feSmcpowers new_objp); 2372*034448feSmcpowers if (rv != CKR_OK) 2373*034448feSmcpowers goto failed_exit; 2374*034448feSmcpowers } else { 2375*034448feSmcpowers crypto_derive_key_t obj_dk; 2376*034448feSmcpowers 23777c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulAttributeCount, 23787c478bd9Sstevel@tonic-gate &obj_dk.dk_attributes, &is_token_obj); 23797c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 23807c478bd9Sstevel@tonic-gate goto failed_exit; 23817c478bd9Sstevel@tonic-gate } 23827c478bd9Sstevel@tonic-gate 23837c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */ 23847c478bd9Sstevel@tonic-gate if (is_token_obj && session_p->ses_RO) { 2385*034448feSmcpowers free_object_attributes(obj_dk.dk_attributes, 2386*034448feSmcpowers ulAttributeCount); 23877c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY; 23887c478bd9Sstevel@tonic-gate goto failed_exit; 23897c478bd9Sstevel@tonic-gate } 23907c478bd9Sstevel@tonic-gate 23917c478bd9Sstevel@tonic-gate obj_dk.dk_session = session_p->k_session; 23927c478bd9Sstevel@tonic-gate obj_dk.dk_mechanism.cm_type = k_mech_type; 23937c478bd9Sstevel@tonic-gate obj_dk.dk_mechanism.cm_param = pMechanism->pParameter; 23947c478bd9Sstevel@tonic-gate obj_dk.dk_mechanism.cm_param_len = pMechanism->ulParameterLen; 23957c478bd9Sstevel@tonic-gate obj_dk.dk_base_key.ck_format = CRYPTO_KEY_REFERENCE; 23967c478bd9Sstevel@tonic-gate obj_dk.dk_base_key.ck_obj_id = basekey_p->k_handle; 23977c478bd9Sstevel@tonic-gate obj_dk.dk_count = ulAttributeCount; 23987c478bd9Sstevel@tonic-gate 23997c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_DERIVE_KEY, &obj_dk)) < 0) { 24007c478bd9Sstevel@tonic-gate if (errno != EINTR) 24017c478bd9Sstevel@tonic-gate break; 24027c478bd9Sstevel@tonic-gate } 24037c478bd9Sstevel@tonic-gate if (r < 0) { 24047c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 24057c478bd9Sstevel@tonic-gate } else { 24067c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_dk.dk_return_value); 24077c478bd9Sstevel@tonic-gate } 24087c478bd9Sstevel@tonic-gate 24097c478bd9Sstevel@tonic-gate free_object_attributes(obj_dk.dk_attributes, ulAttributeCount); 24107c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 24117c478bd9Sstevel@tonic-gate goto failed_exit; 24127c478bd9Sstevel@tonic-gate } 24137c478bd9Sstevel@tonic-gate 24147c478bd9Sstevel@tonic-gate /* Get the CKA_PRIVATE value for the derived key. */ 24157c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_dk.dk_object_handle, 24167c478bd9Sstevel@tonic-gate &is_pri_obj); 24177c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 24187c478bd9Sstevel@tonic-gate goto failed_exit; 24197c478bd9Sstevel@tonic-gate } 24207c478bd9Sstevel@tonic-gate 24217c478bd9Sstevel@tonic-gate /* 2422*034448feSmcpowers * Store the kernel object handle into the new derived key 2423*034448feSmcpowers * object and finish the object initialization. 24247c478bd9Sstevel@tonic-gate */ 24257c478bd9Sstevel@tonic-gate new_objp->is_lib_obj = B_FALSE; 24267c478bd9Sstevel@tonic-gate new_objp->k_handle = obj_dk.dk_object_handle; 24277c478bd9Sstevel@tonic-gate new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 24287c478bd9Sstevel@tonic-gate new_objp->extra_attrlistp = NULL; 24297c478bd9Sstevel@tonic-gate 24307c478bd9Sstevel@tonic-gate if (is_pri_obj) 24317c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 24327c478bd9Sstevel@tonic-gate else 24337c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 24347c478bd9Sstevel@tonic-gate 24357c478bd9Sstevel@tonic-gate if (is_token_obj) 24367c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 24377c478bd9Sstevel@tonic-gate else 24387c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 2439*034448feSmcpowers } 24407c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 24417c478bd9Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 24427c478bd9Sstevel@tonic-gate 24437c478bd9Sstevel@tonic-gate /* 24447c478bd9Sstevel@tonic-gate * Add the new derived object to the slot's token list if it is a 24457c478bd9Sstevel@tonic-gate * token object. Otherwise, add it to the session's object list. 24467c478bd9Sstevel@tonic-gate */ 24477c478bd9Sstevel@tonic-gate if (is_token_obj) { 24487c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 24497c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot); 24507c478bd9Sstevel@tonic-gate } else { 24517c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p); 24527c478bd9Sstevel@tonic-gate } 24537c478bd9Sstevel@tonic-gate 24547c478bd9Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp; 245501223cbaSmcpowers OBJ_REFRELE(basekey_p); 24567c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 24577c478bd9Sstevel@tonic-gate return (rv); 24587c478bd9Sstevel@tonic-gate 24597c478bd9Sstevel@tonic-gate failed_exit: 246001223cbaSmcpowers OBJ_REFRELE(basekey_p); 24617c478bd9Sstevel@tonic-gate if (new_objp != NULL) { 24627c478bd9Sstevel@tonic-gate (void) free(new_objp); 24637c478bd9Sstevel@tonic-gate } 24647c478bd9Sstevel@tonic-gate 24657c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 24667c478bd9Sstevel@tonic-gate return (rv); 24677c478bd9Sstevel@tonic-gate } 2468