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