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