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