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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <strings.h> 307c478bd9Sstevel@tonic-gate #include <errno.h> 317c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 327c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h> 337c478bd9Sstevel@tonic-gate #include "kernelGlobal.h" 347c478bd9Sstevel@tonic-gate #include "kernelSession.h" 357c478bd9Sstevel@tonic-gate #include "kernelObject.h" 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate static boolean_t 387c478bd9Sstevel@tonic-gate is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount) 397c478bd9Sstevel@tonic-gate { 407c478bd9Sstevel@tonic-gate int i; 417c478bd9Sstevel@tonic-gate for (i = 0; i < ulAttributeCount; i++) { 427c478bd9Sstevel@tonic-gate if (pTemplate[i].type == CKA_CLASS && 437c478bd9Sstevel@tonic-gate *(CK_OBJECT_CLASS *)(pTemplate[i].pValue) == 447c478bd9Sstevel@tonic-gate CKO_SECRET_KEY) 457c478bd9Sstevel@tonic-gate return (B_TRUE); 467c478bd9Sstevel@tonic-gate } 477c478bd9Sstevel@tonic-gate return (B_FALSE); 487c478bd9Sstevel@tonic-gate } 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate CK_RV 527c478bd9Sstevel@tonic-gate C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 537c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) 547c478bd9Sstevel@tonic-gate { 557c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 567c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 577c478bd9Sstevel@tonic-gate kernel_object_t *new_objp = NULL; 587c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 597c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 607c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj; 617c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE; 627c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 637c478bd9Sstevel@tonic-gate crypto_object_generate_key_t obj_gk; 647c478bd9Sstevel@tonic-gate int r; 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate if (!kernel_initialized) 677c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate /* Obtain the session pointer */ 707c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 717c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 727c478bd9Sstevel@tonic-gate return (rv); 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate if ((pMechanism == NULL) || (phKey == NULL)) { 757c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 767c478bd9Sstevel@tonic-gate goto failed_exit; 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate if ((pTemplate == NULL) && (ulCount != 0)) { 807c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 817c478bd9Sstevel@tonic-gate goto failed_exit; 827c478bd9Sstevel@tonic-gate } 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 857c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 867c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 877c478bd9Sstevel@tonic-gate goto failed_exit; 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate /* Create an object wrapper in the library first */ 917c478bd9Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t)); 927c478bd9Sstevel@tonic-gate if (new_objp == NULL) { 937c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 947c478bd9Sstevel@tonic-gate goto failed_exit; 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* Process the attributes */ 987c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulCount, 997c478bd9Sstevel@tonic-gate &obj_gk.gk_attributes, &is_token_obj); 1007c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1017c478bd9Sstevel@tonic-gate goto failed_exit; 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */ 1057c478bd9Sstevel@tonic-gate if (is_token_obj && session_p->ses_RO) { 1067c478bd9Sstevel@tonic-gate free_object_attributes(obj_gk.gk_attributes, ulCount); 1077c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY; 1087c478bd9Sstevel@tonic-gate goto failed_exit; 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* Call the CRYPTO_GENERATE_KEY ioctl */ 1127c478bd9Sstevel@tonic-gate obj_gk.gk_session = session_p->k_session; 1137c478bd9Sstevel@tonic-gate obj_gk.gk_count = ulCount; 1147c478bd9Sstevel@tonic-gate obj_gk.gk_mechanism.cm_type = k_mech_type; 1157c478bd9Sstevel@tonic-gate obj_gk.gk_mechanism.cm_param = pMechanism->pParameter; 1167c478bd9Sstevel@tonic-gate obj_gk.gk_mechanism.cm_param_len = pMechanism->ulParameterLen; 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY, &obj_gk)) < 0) { 1197c478bd9Sstevel@tonic-gate if (errno != EINTR) 1207c478bd9Sstevel@tonic-gate break; 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate if (r < 0) { 1237c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 1247c478bd9Sstevel@tonic-gate } else { 1257c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_gk.gk_return_value); 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate free_object_attributes(obj_gk.gk_attributes, ulCount); 1297c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1307c478bd9Sstevel@tonic-gate goto failed_exit; 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* Get the value of the CKA_PRIVATE attribute. */ 1347c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_gk.gk_handle, &is_pri_obj); 1357c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1367c478bd9Sstevel@tonic-gate goto failed_exit; 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* 1407c478bd9Sstevel@tonic-gate * Store the kernel object handle in the object wrapper and 1417c478bd9Sstevel@tonic-gate * initialize the library object. 1427c478bd9Sstevel@tonic-gate */ 1437c478bd9Sstevel@tonic-gate new_objp->k_handle = obj_gk.gk_handle; 1447c478bd9Sstevel@tonic-gate new_objp->is_lib_obj = B_FALSE; 1457c478bd9Sstevel@tonic-gate new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 1467c478bd9Sstevel@tonic-gate new_objp->extra_attrlistp = NULL; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate if (is_pri_obj) 1497c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 1507c478bd9Sstevel@tonic-gate else 1517c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate if (is_token_obj) 1547c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 1557c478bd9Sstevel@tonic-gate else 1567c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 1597c478bd9Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Add the new object to the slot's token object list if it is a 1637c478bd9Sstevel@tonic-gate * a token object. Otherwise, add it to the session's object list. 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate if (is_token_obj) { 1667c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 1677c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot); 1687c478bd9Sstevel@tonic-gate } else { 1697c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp; 1737c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 1747c478bd9Sstevel@tonic-gate return (rv); 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate failed_exit: 1777c478bd9Sstevel@tonic-gate if (new_objp != NULL) { 1787c478bd9Sstevel@tonic-gate (void) free(new_objp); 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 1827c478bd9Sstevel@tonic-gate return (rv); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate CK_RV 1877c478bd9Sstevel@tonic-gate C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 1887c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, 1897c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, 1907c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) 1917c478bd9Sstevel@tonic-gate { 1927c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 1937c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 1947c478bd9Sstevel@tonic-gate kernel_object_t *new_pub_objp = NULL; 1957c478bd9Sstevel@tonic-gate kernel_object_t *new_pri_objp = NULL; 1967c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 1977c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 1987c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj1; 1997c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj2; 2007c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj1 = FALSE; 2017c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj2 = FALSE; 2027c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 2037c478bd9Sstevel@tonic-gate crypto_object_generate_key_pair_t obj_kp; 2047c478bd9Sstevel@tonic-gate int r; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if (!kernel_initialized) 2077c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 2107c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 2117c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 2127c478bd9Sstevel@tonic-gate return (rv); 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate if ((pMechanism == NULL) || (phPublicKey == NULL) || 2157c478bd9Sstevel@tonic-gate (phPrivateKey == NULL)) { 2167c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 2177c478bd9Sstevel@tonic-gate goto failed_exit; 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate if ((pPublicKeyTemplate == NULL) && (ulPublicKeyAttributeCount != 0)) { 2217c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 2227c478bd9Sstevel@tonic-gate goto failed_exit; 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if ((pPrivateKeyTemplate == NULL) && 2267c478bd9Sstevel@tonic-gate (ulPrivateKeyAttributeCount != 0)) { 2277c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 2287c478bd9Sstevel@tonic-gate goto failed_exit; 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 2327c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 2337c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2347c478bd9Sstevel@tonic-gate goto failed_exit; 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* Create an object wrapper for the public key */ 2387c478bd9Sstevel@tonic-gate new_pub_objp = calloc(1, sizeof (kernel_object_t)); 2397c478bd9Sstevel@tonic-gate if (new_pub_objp == NULL) { 2407c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 2417c478bd9Sstevel@tonic-gate goto failed_exit; 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate /* Create an object wrapper for the private key. */ 2457c478bd9Sstevel@tonic-gate new_pri_objp = calloc(1, sizeof (kernel_object_t)); 2467c478bd9Sstevel@tonic-gate if (new_pri_objp == NULL) { 2477c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 2487c478bd9Sstevel@tonic-gate goto failed_exit; 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate /* Process the public key attributes. */ 2527c478bd9Sstevel@tonic-gate rv = process_object_attributes(pPublicKeyTemplate, 2537c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount, &obj_kp.kp_public_attributes, 2547c478bd9Sstevel@tonic-gate &is_token_obj1); 2557c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2567c478bd9Sstevel@tonic-gate goto failed_exit; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */ 2607c478bd9Sstevel@tonic-gate if (is_token_obj1 && session_p->ses_RO) { 2617c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes, 2627c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount); 2637c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY; 2647c478bd9Sstevel@tonic-gate goto failed_exit; 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* Process the private key attributes. */ 2687c478bd9Sstevel@tonic-gate rv = process_object_attributes(pPrivateKeyTemplate, 2697c478bd9Sstevel@tonic-gate ulPrivateKeyAttributeCount, &obj_kp.kp_private_attributes, 2707c478bd9Sstevel@tonic-gate &is_token_obj2); 2717c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2727c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes, 2737c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount); 2747c478bd9Sstevel@tonic-gate goto failed_exit; 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * The public key and the private key need to contain the same 2797c478bd9Sstevel@tonic-gate * attribute values for CKA_TOKEN. 2807c478bd9Sstevel@tonic-gate */ 2817c478bd9Sstevel@tonic-gate if (is_token_obj1 != is_token_obj2) { 2827c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes, 2837c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount); 2847c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_private_attributes, 2857c478bd9Sstevel@tonic-gate ulPrivateKeyAttributeCount); 2867c478bd9Sstevel@tonic-gate rv = CKR_ATTRIBUTE_VALUE_INVALID; 2877c478bd9Sstevel@tonic-gate goto failed_exit; 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate /* Call the CRYPTO_GENERATE_KEY_PAIR ioctl. */ 2917c478bd9Sstevel@tonic-gate obj_kp.kp_session = session_p-> k_session; 2927c478bd9Sstevel@tonic-gate obj_kp.kp_mechanism.cm_type = k_mech_type; 2937c478bd9Sstevel@tonic-gate obj_kp.kp_mechanism.cm_param = pMechanism->pParameter; 2947c478bd9Sstevel@tonic-gate obj_kp.kp_mechanism.cm_param_len = pMechanism->ulParameterLen; 2957c478bd9Sstevel@tonic-gate obj_kp.kp_public_count = ulPublicKeyAttributeCount; 2967c478bd9Sstevel@tonic-gate obj_kp.kp_private_count = ulPrivateKeyAttributeCount; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY_PAIR, &obj_kp)) < 0) { 2997c478bd9Sstevel@tonic-gate if (errno != EINTR) 3007c478bd9Sstevel@tonic-gate break; 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate if (r < 0) { 3037c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 3047c478bd9Sstevel@tonic-gate } else { 3057c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_kp.kp_return_value); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes, 3097c478bd9Sstevel@tonic-gate ulPublicKeyAttributeCount); 3107c478bd9Sstevel@tonic-gate free_object_attributes(obj_kp.kp_private_attributes, 3117c478bd9Sstevel@tonic-gate ulPrivateKeyAttributeCount); 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3147c478bd9Sstevel@tonic-gate goto failed_exit; 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* Get the CKA_PRIVATE value for the key pair. */ 3187c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_kp.kp_public_handle, 3197c478bd9Sstevel@tonic-gate &is_pri_obj1); 3207c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3217c478bd9Sstevel@tonic-gate goto failed_exit; 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_kp.kp_private_handle, 3257c478bd9Sstevel@tonic-gate &is_pri_obj2); 3267c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3277c478bd9Sstevel@tonic-gate goto failed_exit; 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* 3317c478bd9Sstevel@tonic-gate * Store the kernel public key handle into the public key object and 3327c478bd9Sstevel@tonic-gate * finish the public key object initialization. 3337c478bd9Sstevel@tonic-gate */ 3347c478bd9Sstevel@tonic-gate new_pub_objp->is_lib_obj = B_FALSE; 3357c478bd9Sstevel@tonic-gate new_pub_objp->k_handle = obj_kp.kp_public_handle; 3367c478bd9Sstevel@tonic-gate new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; 3377c478bd9Sstevel@tonic-gate new_pub_objp->extra_attrlistp = NULL; 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate if (is_pri_obj1) 3407c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 3417c478bd9Sstevel@tonic-gate else 3427c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate if (is_token_obj1) 3457c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask |= TOKEN_BOOL_ON; 3467c478bd9Sstevel@tonic-gate else 3477c478bd9Sstevel@tonic-gate new_pub_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); 3507c478bd9Sstevel@tonic-gate new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* 3537c478bd9Sstevel@tonic-gate * Store the kernel private key handle into the private key object 3547c478bd9Sstevel@tonic-gate * and finish the private key object initialization. 3557c478bd9Sstevel@tonic-gate */ 3567c478bd9Sstevel@tonic-gate new_pri_objp->is_lib_obj = B_FALSE; 3577c478bd9Sstevel@tonic-gate new_pri_objp->k_handle = obj_kp.kp_private_handle; 3587c478bd9Sstevel@tonic-gate new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; 3597c478bd9Sstevel@tonic-gate new_pri_objp->extra_attrlistp = NULL; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate if (is_pri_obj2) 3627c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 3637c478bd9Sstevel@tonic-gate else 3647c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate if (is_token_obj2) 3677c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask |= TOKEN_BOOL_ON; 3687c478bd9Sstevel@tonic-gate else 3697c478bd9Sstevel@tonic-gate new_pri_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); 3727c478bd9Sstevel@tonic-gate new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate /* 3757c478bd9Sstevel@tonic-gate * Add the new pub/pri objects to the slot's token list if they are 3767c478bd9Sstevel@tonic-gate * token objects. Otherwise, add them to the session's object list. 3777c478bd9Sstevel@tonic-gate */ 3787c478bd9Sstevel@tonic-gate if (is_token_obj1) { /* is_token_obj1 == is_token_obj2 */ 3797c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 3807c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_pub_objp, pslot); 3817c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_pri_objp, pslot); 3827c478bd9Sstevel@tonic-gate } else { 3837c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_pub_objp, session_p); 3847c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_pri_objp, session_p); 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate *phPublicKey = (CK_OBJECT_HANDLE)new_pub_objp; 3887c478bd9Sstevel@tonic-gate *phPrivateKey = (CK_OBJECT_HANDLE)new_pri_objp; 3897c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 3907c478bd9Sstevel@tonic-gate return (rv); 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate failed_exit: 3937c478bd9Sstevel@tonic-gate if (new_pub_objp != NULL) { 3947c478bd9Sstevel@tonic-gate (void) free(new_pub_objp); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate if (new_pri_objp != NULL) { 3987c478bd9Sstevel@tonic-gate (void) free(new_pri_objp); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 4027c478bd9Sstevel@tonic-gate return (rv); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate CK_RV 4077c478bd9Sstevel@tonic-gate C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 4087c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, 4097c478bd9Sstevel@tonic-gate CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) 4107c478bd9Sstevel@tonic-gate { 4117c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 4127c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 4137c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 4147c478bd9Sstevel@tonic-gate kernel_object_t *wrappingkey_p; 4157c478bd9Sstevel@tonic-gate kernel_object_t *key_p; 4167c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 4177c478bd9Sstevel@tonic-gate crypto_object_wrap_key_t obj_wrapkey; 4187c478bd9Sstevel@tonic-gate int r; 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate if (!kernel_initialized) 4217c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if (pulWrappedKeyLen == NULL || pMechanism == NULL) { 4247c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate /* 4287c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session 4297c478bd9Sstevel@tonic-gate * reference count. 4307c478bd9Sstevel@tonic-gate */ 4317c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 4327c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4337c478bd9Sstevel@tonic-gate return (rv); 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 4367c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 4377c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4387c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 4397c478bd9Sstevel@tonic-gate return (rv); 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* Obtain the wrapping key object pointer. */ 4437c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hWrappingKey, wrappingkey_p, rv); 4447c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4457c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 4467c478bd9Sstevel@tonic-gate return (rv); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate /* Obtain the to_be_wrapped key object pointer. */ 4507c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hKey, key_p, rv); 4517c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 45201223cbaSmcpowers OBJ_REFRELE(wrappingkey_p); 4537c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 4547c478bd9Sstevel@tonic-gate return (rv); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate /* Make the CRYPTO_OBJECT_WRAP_KEY ioctl call. */ 4587c478bd9Sstevel@tonic-gate obj_wrapkey.wk_session = session_p->k_session; 4597c478bd9Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_type = k_mech_type; 4607c478bd9Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_param = pMechanism->pParameter; 4617c478bd9Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_param_len = pMechanism->ulParameterLen; 4627c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapping_key.ck_format = CRYPTO_KEY_REFERENCE; 4637c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapping_key.ck_obj_id = wrappingkey_p->k_handle; 4647c478bd9Sstevel@tonic-gate obj_wrapkey.wk_object_handle = key_p->k_handle; 4657c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapped_key_len = *pulWrappedKeyLen; 4667c478bd9Sstevel@tonic-gate obj_wrapkey.wk_wrapped_key = (char *)pWrappedKey; 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_WRAP_KEY, &obj_wrapkey)) < 0) { 4697c478bd9Sstevel@tonic-gate if (errno != EINTR) 4707c478bd9Sstevel@tonic-gate break; 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate if (r < 0) { 4737c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 4747c478bd9Sstevel@tonic-gate } else { 4757c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_wrapkey.wk_return_value); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate /* 4797c478bd9Sstevel@tonic-gate * Besides rv == CKR_OK, we will set the value of pulWrappedKeyLen 4807c478bd9Sstevel@tonic-gate * when the applciation-supplied wrapped key buffer is too small. 4817c478bd9Sstevel@tonic-gate * The situation that the application only asks for the length of 4827c478bd9Sstevel@tonic-gate * the wrapped key is covered in rv == CKR_OK. 4837c478bd9Sstevel@tonic-gate */ 4847c478bd9Sstevel@tonic-gate if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) { 4857c478bd9Sstevel@tonic-gate *pulWrappedKeyLen = obj_wrapkey.wk_wrapped_key_len; 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 48801223cbaSmcpowers OBJ_REFRELE(key_p); 48901223cbaSmcpowers OBJ_REFRELE(wrappingkey_p); 4907c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 4917c478bd9Sstevel@tonic-gate return (rv); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate CK_RV 4967c478bd9Sstevel@tonic-gate C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 4977c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, 4987c478bd9Sstevel@tonic-gate CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, 4997c478bd9Sstevel@tonic-gate CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) 5007c478bd9Sstevel@tonic-gate { 5017c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 5027c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 5037c478bd9Sstevel@tonic-gate kernel_object_t *unwrappingkey_p; 5047c478bd9Sstevel@tonic-gate kernel_object_t *new_objp = NULL; 5057c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 5067c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 5077c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj; 5087c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE; 5097c478bd9Sstevel@tonic-gate CK_MECHANISM_INFO info; 5107c478bd9Sstevel@tonic-gate uint32_t k_mi_flags; 5117c478bd9Sstevel@tonic-gate CK_BYTE *clear_key_val = NULL; 5127c478bd9Sstevel@tonic-gate CK_ULONG ulDataLen; 5137c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_PTR newTemplate = NULL; 5147c478bd9Sstevel@tonic-gate CK_ULONG templ_size; 5157c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 5167c478bd9Sstevel@tonic-gate crypto_object_unwrap_key_t obj_unwrapkey; 5177c478bd9Sstevel@tonic-gate int r; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate if (!kernel_initialized) 5207c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL) { 5237c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate if ((pTemplate == NULL) && (ulAttributeCount != 0)) { 5277c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 5317c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 5327c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 5337c478bd9Sstevel@tonic-gate return (rv); 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate /* Obtain the wrapping key object pointer. */ 5367c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hUnwrappingKey, unwrappingkey_p, rv); 5377c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 53801223cbaSmcpowers REFRELE(session_p, ses_lock_held); 53901223cbaSmcpowers return (rv); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate /* 5437c478bd9Sstevel@tonic-gate * If the HW provider doesn't support C_UnwrapKey, we will try 5447c478bd9Sstevel@tonic-gate * to emulate it in the library. 5457c478bd9Sstevel@tonic-gate */ 5467c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 5477c478bd9Sstevel@tonic-gate if ((pslot->sl_func_list.fl_object_create == B_FALSE) && 5487c478bd9Sstevel@tonic-gate (pslot->sl_func_list.fl_key_unwrap == B_FALSE)) { 5497c478bd9Sstevel@tonic-gate rv = get_mechanism_info(pslot, pMechanism->mechanism, &info, 5507c478bd9Sstevel@tonic-gate &k_mi_flags); 5517c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 5527c478bd9Sstevel@tonic-gate goto failed_exit; 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate /* 5567c478bd9Sstevel@tonic-gate * If the mechanism flag doesn't have CKF_UNWRAP, and it's 5577c478bd9Sstevel@tonic-gate * an unwrapping of a secret key object, then help this 5587c478bd9Sstevel@tonic-gate * out with a decryption followed by an object creation. 5597c478bd9Sstevel@tonic-gate */ 5607c478bd9Sstevel@tonic-gate if (!(k_mi_flags & CRYPTO_FG_UNWRAP) && 5617c478bd9Sstevel@tonic-gate (k_mi_flags & CRYPTO_FG_DECRYPT) && 5627c478bd9Sstevel@tonic-gate (is_secret_key_template(pTemplate, ulAttributeCount))) { 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate /* First allocate space for the recovered key value */ 5657c478bd9Sstevel@tonic-gate clear_key_val = malloc(ulWrappedKeyLen); 5667c478bd9Sstevel@tonic-gate if (clear_key_val == NULL) { 5677c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 5687c478bd9Sstevel@tonic-gate goto failed_exit; 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate rv = kernel_decrypt_init(session_p, unwrappingkey_p, 5727c478bd9Sstevel@tonic-gate pMechanism); 5737c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 5747c478bd9Sstevel@tonic-gate goto failed_exit; 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate ulDataLen = ulWrappedKeyLen; 5787c478bd9Sstevel@tonic-gate rv = kernel_decrypt(session_p, pWrappedKey, 5797c478bd9Sstevel@tonic-gate ulWrappedKeyLen, clear_key_val, &ulDataLen); 5807c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 5817c478bd9Sstevel@tonic-gate goto failed_exit; 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate /* Now add the CKA_VALUE attribute to template */ 5857c478bd9Sstevel@tonic-gate templ_size = ulAttributeCount * sizeof (CK_ATTRIBUTE); 5867c478bd9Sstevel@tonic-gate newTemplate = malloc(templ_size + 5877c478bd9Sstevel@tonic-gate sizeof (CK_ATTRIBUTE)); 5887c478bd9Sstevel@tonic-gate if (newTemplate == NULL) { 5897c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 5907c478bd9Sstevel@tonic-gate goto failed_exit; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate bcopy(pTemplate, newTemplate, templ_size); 5947c478bd9Sstevel@tonic-gate newTemplate[ulAttributeCount].type = CKA_VALUE; 5957c478bd9Sstevel@tonic-gate newTemplate[ulAttributeCount].pValue = clear_key_val; 5967c478bd9Sstevel@tonic-gate newTemplate[ulAttributeCount].ulValueLen = ulDataLen; 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate /* Finally create the key, based on the new template */ 5997c478bd9Sstevel@tonic-gate rv = kernel_add_object(newTemplate, 6007c478bd9Sstevel@tonic-gate ulAttributeCount + 1, phKey, session_p); 6017c478bd9Sstevel@tonic-gate (void) free(clear_key_val); 6027c478bd9Sstevel@tonic-gate (void) free(newTemplate); 60301223cbaSmcpowers OBJ_REFRELE(unwrappingkey_p); 6047c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 6057c478bd9Sstevel@tonic-gate return (rv); 6067c478bd9Sstevel@tonic-gate } else { 6077c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 6087c478bd9Sstevel@tonic-gate goto failed_exit; 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate /* 6137c478bd9Sstevel@tonic-gate * If we come here, the HW provider must have registered the unwrapkey 6147c478bd9Sstevel@tonic-gate * entry. Therefore, the unwrap key will be performed in the HW 6157c478bd9Sstevel@tonic-gate * provider. 6167c478bd9Sstevel@tonic-gate */ 6177c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 6187c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 6197c478bd9Sstevel@tonic-gate goto failed_exit; 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate /* Create an object wrapper for the new key in the library first */ 6237c478bd9Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t)); 6247c478bd9Sstevel@tonic-gate if (new_objp == NULL) { 6257c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 6267c478bd9Sstevel@tonic-gate goto failed_exit; 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate /* Process the attributes */ 6307c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulAttributeCount, 6317c478bd9Sstevel@tonic-gate &obj_unwrapkey.uk_attributes, &is_token_obj); 6327c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 6337c478bd9Sstevel@tonic-gate goto failed_exit; 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */ 6377c478bd9Sstevel@tonic-gate if (is_token_obj && session_p->ses_RO) { 6387c478bd9Sstevel@tonic-gate free_object_attributes(obj_unwrapkey.uk_attributes, 6397c478bd9Sstevel@tonic-gate ulAttributeCount); 6407c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY; 6417c478bd9Sstevel@tonic-gate goto failed_exit; 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* Make the CRYPTO_UNWRAP_KEY ioctl call. */ 6457c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_session = session_p->k_session; 6467c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_type = k_mech_type; 6477c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_param = pMechanism->pParameter; 6487c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_param_len = pMechanism->ulParameterLen; 6497c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_unwrapping_key.ck_format = CRYPTO_KEY_REFERENCE; 6507c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_unwrapping_key.ck_obj_id = unwrappingkey_p->k_handle; 6517c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_wrapped_key = (char *)pWrappedKey; 6527c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_wrapped_key_len = ulWrappedKeyLen; 6537c478bd9Sstevel@tonic-gate obj_unwrapkey.uk_count = ulAttributeCount; 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_UNWRAP_KEY, &obj_unwrapkey)) < 0) { 6567c478bd9Sstevel@tonic-gate if (errno != EINTR) 6577c478bd9Sstevel@tonic-gate break; 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate if (r < 0) { 6607c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 6617c478bd9Sstevel@tonic-gate } else { 6627c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_unwrapkey.uk_return_value); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate free_object_attributes(obj_unwrapkey.uk_attributes, ulAttributeCount); 6667c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 6677c478bd9Sstevel@tonic-gate goto failed_exit; 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate /* Get the CKA_PRIVATE value for the unwrapped key. */ 6717c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_unwrapkey.uk_object_handle, 6727c478bd9Sstevel@tonic-gate &is_pri_obj); 6737c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 6747c478bd9Sstevel@tonic-gate goto failed_exit; 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate /* 6787c478bd9Sstevel@tonic-gate * Store the kernel object handle in the new key object wrapper and 6797c478bd9Sstevel@tonic-gate * initialize it. 6807c478bd9Sstevel@tonic-gate */ 6817c478bd9Sstevel@tonic-gate new_objp->k_handle = obj_unwrapkey.uk_object_handle; 6827c478bd9Sstevel@tonic-gate new_objp->is_lib_obj = B_FALSE; 6837c478bd9Sstevel@tonic-gate new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 6847c478bd9Sstevel@tonic-gate new_objp->extra_attrlistp = NULL; 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate if (is_pri_obj) 6877c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 6887c478bd9Sstevel@tonic-gate else 6897c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate if (is_token_obj) 6927c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 6937c478bd9Sstevel@tonic-gate else 6947c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 6977c478bd9Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate /* 7007c478bd9Sstevel@tonic-gate * Add the new object to the slot's token object list if it is a 7017c478bd9Sstevel@tonic-gate * a token object. Otherwise, add it to the session's object list. 7027c478bd9Sstevel@tonic-gate */ 7037c478bd9Sstevel@tonic-gate if (is_token_obj) { 7047c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 7057c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot); 7067c478bd9Sstevel@tonic-gate } else { 7077c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p); 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp; 71101223cbaSmcpowers OBJ_REFRELE(unwrappingkey_p); 7127c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 7137c478bd9Sstevel@tonic-gate return (rv); 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate failed_exit: 71601223cbaSmcpowers OBJ_REFRELE(unwrappingkey_p); 7177c478bd9Sstevel@tonic-gate if (new_objp != NULL) 7187c478bd9Sstevel@tonic-gate (void) free(new_objp); 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate if (clear_key_val != NULL) 7217c478bd9Sstevel@tonic-gate (void) free(clear_key_val); 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate if (newTemplate != NULL) 7247c478bd9Sstevel@tonic-gate (void) free(newTemplate); 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 7277c478bd9Sstevel@tonic-gate return (rv); 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate CK_RV 7327c478bd9Sstevel@tonic-gate C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 7337c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, 7347c478bd9Sstevel@tonic-gate CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) 7357c478bd9Sstevel@tonic-gate { 7367c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 7377c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 7387c478bd9Sstevel@tonic-gate kernel_object_t *basekey_p; 7397c478bd9Sstevel@tonic-gate kernel_object_t *new_objp; 7407c478bd9Sstevel@tonic-gate kernel_slot_t *pslot; 7417c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 7427c478bd9Sstevel@tonic-gate CK_BBOOL is_pri_obj; 7437c478bd9Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE; 7447c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 7457c478bd9Sstevel@tonic-gate crypto_derive_key_t obj_dk; 7467c478bd9Sstevel@tonic-gate int r; 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate if (!kernel_initialized) 7497c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 7527c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 7537c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 7547c478bd9Sstevel@tonic-gate return (rv); 7557c478bd9Sstevel@tonic-gate 756*60722cc8Sizick if (pMechanism == NULL) { 75701223cbaSmcpowers REFRELE(session_p, ses_lock_held); 75801223cbaSmcpowers return (CKR_ARGUMENTS_BAD); 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate if ((pTemplate == NULL && ulAttributeCount != 0) || 7627c478bd9Sstevel@tonic-gate (pTemplate != NULL && ulAttributeCount == 0)) { 76301223cbaSmcpowers REFRELE(session_p, ses_lock_held); 76401223cbaSmcpowers return (CKR_ARGUMENTS_BAD); 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate /* Obtain the base key object pointer. */ 7687c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hBaseKey, basekey_p, rv); 7697c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 77001223cbaSmcpowers REFRELE(session_p, ses_lock_held); 77101223cbaSmcpowers return (rv); 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 7757c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 7767c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 7777c478bd9Sstevel@tonic-gate goto failed_exit; 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate /* Create an object wrapper in the library for the generated key. */ 7817c478bd9Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t)); 7827c478bd9Sstevel@tonic-gate if (new_objp == NULL) { 7837c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 7847c478bd9Sstevel@tonic-gate goto failed_exit; 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate /* Process the attributes */ 7887c478bd9Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulAttributeCount, 7897c478bd9Sstevel@tonic-gate &obj_dk.dk_attributes, &is_token_obj); 7907c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 7917c478bd9Sstevel@tonic-gate goto failed_exit; 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */ 7957c478bd9Sstevel@tonic-gate if (is_token_obj && session_p->ses_RO) { 7967c478bd9Sstevel@tonic-gate free_object_attributes(obj_dk.dk_attributes, ulAttributeCount); 7977c478bd9Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY; 7987c478bd9Sstevel@tonic-gate goto failed_exit; 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate /* Call the CRYPTO_DERIVE_KEY ioctl */ 8027c478bd9Sstevel@tonic-gate obj_dk.dk_session = session_p->k_session; 8037c478bd9Sstevel@tonic-gate obj_dk.dk_mechanism.cm_type = k_mech_type; 8047c478bd9Sstevel@tonic-gate obj_dk.dk_mechanism.cm_param = pMechanism->pParameter; 8057c478bd9Sstevel@tonic-gate obj_dk.dk_mechanism.cm_param_len = pMechanism->ulParameterLen; 8067c478bd9Sstevel@tonic-gate obj_dk.dk_base_key.ck_format = CRYPTO_KEY_REFERENCE; 8077c478bd9Sstevel@tonic-gate obj_dk.dk_base_key.ck_obj_id = basekey_p->k_handle; 8087c478bd9Sstevel@tonic-gate obj_dk.dk_count = ulAttributeCount; 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_DERIVE_KEY, &obj_dk)) < 0) { 8117c478bd9Sstevel@tonic-gate if (errno != EINTR) 8127c478bd9Sstevel@tonic-gate break; 8137c478bd9Sstevel@tonic-gate } 8147c478bd9Sstevel@tonic-gate if (r < 0) { 8157c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 8167c478bd9Sstevel@tonic-gate } else { 8177c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_dk.dk_return_value); 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate free_object_attributes(obj_dk.dk_attributes, ulAttributeCount); 8217c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 8227c478bd9Sstevel@tonic-gate goto failed_exit; 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate /* Get the CKA_PRIVATE value for the derived key. */ 8267c478bd9Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_dk.dk_object_handle, 8277c478bd9Sstevel@tonic-gate &is_pri_obj); 8287c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 8297c478bd9Sstevel@tonic-gate goto failed_exit; 8307c478bd9Sstevel@tonic-gate } 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate /* 8337c478bd9Sstevel@tonic-gate * Store the kernel object handle into the new derived key object 8347c478bd9Sstevel@tonic-gate * and finish the object initialization. 8357c478bd9Sstevel@tonic-gate */ 8367c478bd9Sstevel@tonic-gate new_objp->is_lib_obj = B_FALSE; 8377c478bd9Sstevel@tonic-gate new_objp->k_handle = obj_dk.dk_object_handle; 8387c478bd9Sstevel@tonic-gate new_objp->session_handle = (CK_SESSION_HANDLE)session_p; 8397c478bd9Sstevel@tonic-gate new_objp->extra_attrlistp = NULL; 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate if (is_pri_obj) 8427c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; 8437c478bd9Sstevel@tonic-gate else 8447c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate if (is_token_obj) 8477c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask |= TOKEN_BOOL_ON; 8487c478bd9Sstevel@tonic-gate else 8497c478bd9Sstevel@tonic-gate new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL); 8527c478bd9Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate /* 8557c478bd9Sstevel@tonic-gate * Add the new derived object to the slot's token list if it is a 8567c478bd9Sstevel@tonic-gate * token object. Otherwise, add it to the session's object list. 8577c478bd9Sstevel@tonic-gate */ 8587c478bd9Sstevel@tonic-gate if (is_token_obj) { 8597c478bd9Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid]; 8607c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot); 8617c478bd9Sstevel@tonic-gate } else { 8627c478bd9Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p); 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp; 86601223cbaSmcpowers OBJ_REFRELE(basekey_p); 8677c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 8687c478bd9Sstevel@tonic-gate return (rv); 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate failed_exit: 87101223cbaSmcpowers OBJ_REFRELE(basekey_p); 8727c478bd9Sstevel@tonic-gate if (new_objp != NULL) { 8737c478bd9Sstevel@tonic-gate (void) free(new_objp); 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 8777c478bd9Sstevel@tonic-gate return (rv); 8787c478bd9Sstevel@tonic-gate } 879