10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
54219Smcpowers * Common Development and Distribution License (the "License").
64219Smcpowers * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*10669SMark.Powers@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <strings.h>
270Sstevel@tonic-gate #include <errno.h>
285697Smcpowers #include <ecc_impl.h>
290Sstevel@tonic-gate #include <security/cryptoki.h>
300Sstevel@tonic-gate #include <sys/crypto/ioctl.h>
310Sstevel@tonic-gate #include "kernelGlobal.h"
320Sstevel@tonic-gate #include "kernelSession.h"
330Sstevel@tonic-gate #include "kernelObject.h"
340Sstevel@tonic-gate
350Sstevel@tonic-gate static boolean_t
attribute_in_template(CK_ATTRIBUTE_TYPE type,CK_ATTRIBUTE_PTR t,CK_ULONG cnt)364219Smcpowers attribute_in_template(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR t, CK_ULONG cnt)
374219Smcpowers {
384219Smcpowers int i;
394219Smcpowers
404219Smcpowers for (i = 0; i < cnt; i++) {
414219Smcpowers if (t[i].type == type)
424219Smcpowers return (B_TRUE);
434219Smcpowers }
444219Smcpowers return (B_FALSE);
454219Smcpowers }
464219Smcpowers
474219Smcpowers /*
484219Smcpowers * This routine returns modulus bytes rounded up to the nearest 8 byte
494219Smcpowers * chunk. This is so we don't have to pass in max sized buffers for
504219Smcpowers * returned attributes. Every unnecessary byte that we pass in results
514219Smcpowers * in a kernel allocation.
524219Smcpowers */
534219Smcpowers static ulong_t
get_modulus_bytes(CK_ATTRIBUTE_PTR t,CK_ULONG cnt)544219Smcpowers get_modulus_bytes(CK_ATTRIBUTE_PTR t, CK_ULONG cnt)
554219Smcpowers {
564219Smcpowers CK_ULONG modulus_len;
574219Smcpowers int i;
584219Smcpowers
594219Smcpowers for (i = 0; i < cnt; i++) {
604219Smcpowers if (t[i].type == CKA_MODULUS_BITS) {
614219Smcpowers get_ulong_attr_from_template(&modulus_len, &t[i]);
624219Smcpowers /* convert from bit length to byte length */
634219Smcpowers modulus_len = (modulus_len - 1) / 64 + 1;
644219Smcpowers return (modulus_len * 8);
654219Smcpowers }
664219Smcpowers }
674219Smcpowers return (0);
684219Smcpowers }
694219Smcpowers
704219Smcpowers /*
714219Smcpowers * Remove specified attribute from array. Storage for the attribute's
724219Smcpowers * value is freed if 'free_attr' is TRUE. Attributes are shifted so they are
734219Smcpowers * contiguous within the array, i.e. the next attribute is shifted into
744219Smcpowers * the position of the removed attribute. Returns TRUE if specified
754219Smcpowers * attribute is removed.
764219Smcpowers */
774219Smcpowers static boolean_t
remove_one_attribute(CK_ATTRIBUTE_PTR t,CK_ULONG type,uint_t count,boolean_t free_attr)784219Smcpowers remove_one_attribute(CK_ATTRIBUTE_PTR t, CK_ULONG type, uint_t count,
794219Smcpowers boolean_t free_attr)
804219Smcpowers {
814219Smcpowers int i, j;
824219Smcpowers
834219Smcpowers for (i = 0, j = 0; i < count; i++) {
844219Smcpowers if (t[i].type == type) {
854219Smcpowers if (free_attr) {
864219Smcpowers free(t[i].pValue);
874219Smcpowers }
884219Smcpowers continue;
894219Smcpowers }
904219Smcpowers if (i != j) {
914219Smcpowers t[j].type = t[i].type;
924219Smcpowers t[j].pValue = t[i].pValue;
934219Smcpowers t[j].ulValueLen = t[i].ulValueLen;
944219Smcpowers }
954219Smcpowers j++;
964219Smcpowers }
974219Smcpowers if (j == count)
984219Smcpowers return (B_FALSE);
994219Smcpowers
1004219Smcpowers /* safety */
1014219Smcpowers t[j].pValue = NULL;
1024219Smcpowers t[j].ulValueLen = 0;
1034219Smcpowers return (B_TRUE);
1044219Smcpowers }
1054219Smcpowers
1064219Smcpowers static boolean_t
is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount)1070Sstevel@tonic-gate is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount)
1080Sstevel@tonic-gate {
1090Sstevel@tonic-gate int i;
1100Sstevel@tonic-gate for (i = 0; i < ulAttributeCount; i++) {
1110Sstevel@tonic-gate if (pTemplate[i].type == CKA_CLASS &&
1120Sstevel@tonic-gate *(CK_OBJECT_CLASS *)(pTemplate[i].pValue) ==
1130Sstevel@tonic-gate CKO_SECRET_KEY)
1140Sstevel@tonic-gate return (B_TRUE);
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate return (B_FALSE);
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate
1194219Smcpowers /*
1204219Smcpowers * Allocate a template with space for new_count entries and copy the
1214219Smcpowers * specified template into the new template.
1224219Smcpowers */
1234219Smcpowers static CK_ATTRIBUTE_PTR
grow_template(CK_ATTRIBUTE_PTR old_template,CK_ULONG old_count,CK_ULONG new_count)1244219Smcpowers grow_template(CK_ATTRIBUTE_PTR old_template, CK_ULONG old_count,
1254219Smcpowers CK_ULONG new_count)
1264219Smcpowers {
1274219Smcpowers CK_ATTRIBUTE_PTR new_template;
1284219Smcpowers
1294219Smcpowers new_template = malloc(new_count * sizeof (CK_ATTRIBUTE));
1304219Smcpowers if (new_template != NULL)
1314219Smcpowers bcopy(old_template, new_template,
1324219Smcpowers old_count * sizeof (CK_ATTRIBUTE));
1334219Smcpowers return (new_template);
1344219Smcpowers }
1354219Smcpowers
1364219Smcpowers /*
1374219Smcpowers * For fixed length keys such as DES, return the length based on
1384219Smcpowers * the key type. For variable length keys such as AES, take the
1394219Smcpowers * length from the CKA_VALUE_LEN attribute.
1404219Smcpowers */
1414219Smcpowers static int
get_key_len_from_template(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,kernel_object_t * basekey_p,ulong_t * key_len)1424219Smcpowers get_key_len_from_template(CK_MECHANISM_PTR pMechanism,
1434219Smcpowers CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
1444219Smcpowers kernel_object_t *basekey_p, ulong_t *key_len)
1454219Smcpowers {
1464219Smcpowers boolean_t fixed_len_key = B_FALSE;
1474219Smcpowers ulong_t key_type;
1484219Smcpowers int i;
1494219Smcpowers
1504219Smcpowers for (i = 0; i < ulAttributeCount; i++) {
1514219Smcpowers if (pTemplate[i].type == CKA_KEY_TYPE) {
1524219Smcpowers get_ulong_attr_from_template(&key_type, &pTemplate[i]);
1534219Smcpowers break;
1544219Smcpowers }
1554219Smcpowers }
1564219Smcpowers /* CKA_KEY_TYPE must be present */
1574219Smcpowers if (i == ulAttributeCount)
1584219Smcpowers return (CKR_TEMPLATE_INCOMPLETE);
1594219Smcpowers
1604219Smcpowers switch (key_type) {
1614219Smcpowers case CKK_DES:
1624219Smcpowers *key_len = 8;
1634219Smcpowers fixed_len_key = B_TRUE;
1644219Smcpowers break;
1654219Smcpowers case CKK_DES3:
1664219Smcpowers *key_len = 24;
1674219Smcpowers fixed_len_key = B_TRUE;
1684219Smcpowers break;
1694219Smcpowers case CKK_AES:
1704219Smcpowers case CKK_BLOWFISH:
1714219Smcpowers for (i = 0; i < ulAttributeCount; i++) {
1724219Smcpowers if (pTemplate[i].type == CKA_VALUE_LEN) {
1734219Smcpowers get_ulong_attr_from_template(key_len,
1744219Smcpowers &pTemplate[i]);
1754219Smcpowers break;
1764219Smcpowers }
1774219Smcpowers }
1784219Smcpowers /* CKA_VALUE_LEN must be present */
1794219Smcpowers if (i == ulAttributeCount)
1804219Smcpowers return (CKR_TEMPLATE_INCOMPLETE);
1814219Smcpowers break;
1824219Smcpowers case CKK_GENERIC_SECRET:
1834219Smcpowers /*
1844219Smcpowers * The key will not be truncated, so we need to
1854219Smcpowers * get the max length for the mechanism.
1864219Smcpowers */
1874219Smcpowers if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE) {
1884219Smcpowers CK_ATTRIBUTE tmp;
1894219Smcpowers
1904219Smcpowers tmp.type = CKA_PRIME;
1914219Smcpowers tmp.pValue = NULL;
1924219Smcpowers
1934219Smcpowers /* get size of attribute */
1944219Smcpowers if (kernel_get_attribute(basekey_p, &tmp) != CKR_OK) {
1954219Smcpowers return (CKR_ARGUMENTS_BAD);
1964219Smcpowers }
1974219Smcpowers *key_len = tmp.ulValueLen;
1985613Smcpowers } else if (pMechanism->mechanism == CKM_ECDH1_DERIVE) {
1995697Smcpowers *key_len = EC_MAX_VALUE_LEN;
2004219Smcpowers } else {
2014219Smcpowers return (CKR_ARGUMENTS_BAD);
2024219Smcpowers }
2034219Smcpowers break;
2044219Smcpowers default:
2054219Smcpowers return (CKR_ATTRIBUTE_VALUE_INVALID);
2064219Smcpowers }
2074219Smcpowers
2084219Smcpowers if (fixed_len_key && attribute_in_template(CKA_VALUE_LEN,
2094219Smcpowers pTemplate, ulAttributeCount))
2104219Smcpowers return (CKR_TEMPLATE_INCONSISTENT);
2114219Smcpowers
2124219Smcpowers return (CKR_OK);
2134219Smcpowers }
2144219Smcpowers
2154219Smcpowers /* find specified attribute src template and copy to dest */
2164219Smcpowers static int
copy_attribute(CK_ULONG type,CK_ATTRIBUTE_PTR src,CK_ULONG src_cnt,CK_ATTRIBUTE_PTR dst)2174219Smcpowers copy_attribute(CK_ULONG type, CK_ATTRIBUTE_PTR src, CK_ULONG src_cnt,
2184219Smcpowers CK_ATTRIBUTE_PTR dst)
2194219Smcpowers {
2204219Smcpowers int rv, i;
2214219Smcpowers
2224219Smcpowers for (i = 0; i < src_cnt; i++) {
2234219Smcpowers if (src[i].type == type) {
2244219Smcpowers rv = get_string_from_template(dst, &src[i]);
2254219Smcpowers break;
2264219Smcpowers }
2274219Smcpowers }
2284219Smcpowers /*
2294219Smcpowers * The public template didn't have attribute.
2304219Smcpowers */
2314219Smcpowers if (i == src_cnt) {
2324219Smcpowers rv = CKR_TEMPLATE_INCOMPLETE;
2334219Smcpowers }
2344219Smcpowers return (rv);
2354219Smcpowers }
2364219Smcpowers
2374219Smcpowers static void
free_attributes(caddr_t p,uint_t * countp)2384219Smcpowers free_attributes(caddr_t p, uint_t *countp)
2394219Smcpowers {
2404219Smcpowers if (*countp > 0) {
2414219Smcpowers free_object_attributes(p, *countp);
2424219Smcpowers *countp = 0;
2434219Smcpowers }
2444219Smcpowers }
2454219Smcpowers
2464219Smcpowers CK_RV
key_gen_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_objp)2474219Smcpowers key_gen_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate,
2484219Smcpowers CK_ULONG ulCount, kernel_session_t *session_p,
2494219Smcpowers crypto_mech_type_t k_mech_type, kernel_object_t *new_objp)
2504219Smcpowers {
2514219Smcpowers crypto_nostore_generate_key_t obj_ngk;
2524219Smcpowers char *key_buf = NULL;
2534219Smcpowers CK_ATTRIBUTE_PTR newTemplate = NULL;
2544219Smcpowers CK_BBOOL is_token_obj = FALSE;
2554219Smcpowers CK_RV rv = CKR_OK;
2564219Smcpowers ulong_t key_len = 0;
2574219Smcpowers uint_t attr_count;
2584219Smcpowers int r;
2594219Smcpowers
2604219Smcpowers obj_ngk.ngk_in_count = 0;
2614219Smcpowers obj_ngk.ngk_out_count = 0;
2624219Smcpowers
2634219Smcpowers rv = get_key_len_from_template(pMechanism, pTemplate, ulCount,
2644219Smcpowers NULL, &key_len);
2654219Smcpowers if (rv != CRYPTO_SUCCESS)
2664219Smcpowers goto failed_exit;
2674219Smcpowers
2684219Smcpowers if ((key_buf = malloc(key_len)) == NULL) {
2694219Smcpowers rv = CKR_HOST_MEMORY;
2704219Smcpowers goto failed_exit;
2714219Smcpowers }
2724219Smcpowers
2734219Smcpowers attr_count = ulCount + 1;
2744219Smcpowers newTemplate = grow_template(pTemplate, ulCount, attr_count);
2754219Smcpowers if (newTemplate == NULL) {
2764219Smcpowers rv = CKR_HOST_MEMORY;
2774219Smcpowers goto failed_exit;
2784219Smcpowers }
2794219Smcpowers
2804219Smcpowers /* Now add the CKA_VALUE attribute to template */
2814219Smcpowers newTemplate[ulCount].type = CKA_VALUE;
2824219Smcpowers newTemplate[ulCount].pValue = (caddr_t)key_buf;
2834219Smcpowers newTemplate[ulCount].ulValueLen = key_len;
2844219Smcpowers
2854219Smcpowers rv = process_object_attributes(newTemplate, attr_count - 1,
2864219Smcpowers &obj_ngk.ngk_in_attributes, &is_token_obj);
2874219Smcpowers if (rv != CKR_OK) {
2884219Smcpowers goto failed_exit;
2894219Smcpowers }
2904219Smcpowers rv = process_object_attributes(&newTemplate[ulCount],
2914219Smcpowers 1, &obj_ngk.ngk_out_attributes, &is_token_obj);
2924219Smcpowers if (rv != CKR_OK) {
2934219Smcpowers goto failed_exit;
2944219Smcpowers }
2954219Smcpowers
2964219Smcpowers /* Cannot create a token object with a READ-ONLY session. */
2974219Smcpowers if (is_token_obj && session_p->ses_RO) {
2984219Smcpowers rv = CKR_SESSION_READ_ONLY;
2994219Smcpowers goto failed_exit;
3004219Smcpowers }
3014219Smcpowers
3024219Smcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY ioctl */
3034219Smcpowers obj_ngk.ngk_session = session_p->k_session;
3044219Smcpowers obj_ngk.ngk_in_count = attr_count - 1;
3054219Smcpowers obj_ngk.ngk_out_count = 1;
3064219Smcpowers obj_ngk.ngk_mechanism.cm_type = k_mech_type;
3074219Smcpowers obj_ngk.ngk_mechanism.cm_param = pMechanism->pParameter;
3084219Smcpowers obj_ngk.ngk_mechanism.cm_param_len = pMechanism->ulParameterLen;
3094219Smcpowers
3104219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY,
3114219Smcpowers &obj_ngk)) < 0) {
3124219Smcpowers if (errno != EINTR)
3134219Smcpowers break;
3144219Smcpowers }
3154219Smcpowers if (r < 0) {
3164219Smcpowers rv = CKR_FUNCTION_FAILED;
3174219Smcpowers } else {
3184219Smcpowers rv = crypto2pkcs11_error_number(obj_ngk.ngk_return_value);
3194219Smcpowers }
3204219Smcpowers free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count);
3214219Smcpowers if (rv != CKR_OK) {
3224219Smcpowers goto failed_exit;
3234219Smcpowers }
3244219Smcpowers
3254219Smcpowers rv = get_object_attributes(&newTemplate[ulCount], 1,
3264219Smcpowers obj_ngk.ngk_out_attributes);
3274219Smcpowers free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count);
3284219Smcpowers if (rv != CRYPTO_SUCCESS) {
3294219Smcpowers goto failed_exit;
3304219Smcpowers }
3314219Smcpowers
3324219Smcpowers /*
3334219Smcpowers * CKA_VALUE_LEN is not stored with the secret key object,
3344219Smcpowers * so we remove it by shifting attributes down one.
3354219Smcpowers */
3364219Smcpowers (void) remove_one_attribute(newTemplate, CKA_VALUE_LEN,
3374219Smcpowers attr_count, B_FALSE);
3384219Smcpowers
3394219Smcpowers rv = kernel_build_object(newTemplate, attr_count - 1,
3404219Smcpowers new_objp, session_p, KERNEL_GEN_KEY);
3414219Smcpowers if (rv != CRYPTO_SUCCESS) {
3424219Smcpowers goto failed_exit;
3434219Smcpowers }
3444219Smcpowers new_objp->is_lib_obj = B_TRUE;
3454219Smcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
3464219Smcpowers (void) free(newTemplate);
3474219Smcpowers bzero(key_buf, key_len);
3484219Smcpowers (void) free(key_buf);
3494219Smcpowers return (CKR_OK);
3504219Smcpowers
3514219Smcpowers failed_exit:
3524219Smcpowers free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count);
3534219Smcpowers free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count);
3544219Smcpowers if (key_buf != NULL) {
3554219Smcpowers bzero(key_buf, key_len);
3564219Smcpowers (void) free(key_buf);
3574219Smcpowers }
3584219Smcpowers if (newTemplate != NULL) {
3594219Smcpowers (void) free(newTemplate);
3604219Smcpowers }
3614219Smcpowers return (rv);
3624219Smcpowers }
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate CK_RV
C_GenerateKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phKey)3650Sstevel@tonic-gate C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
3660Sstevel@tonic-gate CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
3670Sstevel@tonic-gate {
3680Sstevel@tonic-gate CK_RV rv = CKR_OK;
3690Sstevel@tonic-gate kernel_session_t *session_p;
3700Sstevel@tonic-gate kernel_object_t *new_objp = NULL;
3710Sstevel@tonic-gate kernel_slot_t *pslot;
3720Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE;
3730Sstevel@tonic-gate CK_BBOOL is_pri_obj;
3740Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE;
3750Sstevel@tonic-gate crypto_mech_type_t k_mech_type;
3760Sstevel@tonic-gate int r;
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate if (!kernel_initialized)
3790Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate /* Obtain the session pointer */
3820Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
3830Sstevel@tonic-gate if (rv != CKR_OK)
3840Sstevel@tonic-gate return (rv);
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate if ((pMechanism == NULL) || (phKey == NULL)) {
3870Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
3880Sstevel@tonic-gate goto failed_exit;
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate if ((pTemplate == NULL) && (ulCount != 0)) {
3920Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
3930Sstevel@tonic-gate goto failed_exit;
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */
3970Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
3980Sstevel@tonic-gate if (rv != CKR_OK) {
3990Sstevel@tonic-gate goto failed_exit;
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate /* Create an object wrapper in the library first */
4030Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t));
4040Sstevel@tonic-gate if (new_objp == NULL) {
4050Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
4060Sstevel@tonic-gate goto failed_exit;
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate
4094219Smcpowers /*
4104219Smcpowers * Special Case: if token does not support object creation,
4114219Smcpowers * but does support key generation by value, then create a session
4124219Smcpowers * object and initialize with value returned by token.
4134219Smcpowers */
4144219Smcpowers pslot = slot_table[session_p->ses_slotid];
4154219Smcpowers if (!pslot->sl_func_list.fl_object_create) {
4164219Smcpowers rv = key_gen_by_value(pMechanism, pTemplate, ulCount, session_p,
4174219Smcpowers k_mech_type, new_objp);
4184219Smcpowers if (rv != CKR_OK)
4194219Smcpowers goto failed_exit;
4204219Smcpowers } else {
4214219Smcpowers crypto_object_generate_key_t obj_gk;
4220Sstevel@tonic-gate
4234219Smcpowers /* Process the attributes */
4244219Smcpowers rv = process_object_attributes(pTemplate, ulCount,
4254219Smcpowers &obj_gk.gk_attributes, &is_token_obj);
4264219Smcpowers if (rv != CKR_OK) {
4274219Smcpowers goto failed_exit;
4284219Smcpowers }
4294219Smcpowers /* Cannot create a token object with a READ-ONLY session. */
4304219Smcpowers if (is_token_obj && session_p->ses_RO) {
4314219Smcpowers free_object_attributes(obj_gk.gk_attributes, ulCount);
4324219Smcpowers rv = CKR_SESSION_READ_ONLY;
4334219Smcpowers goto failed_exit;
4344219Smcpowers }
4354219Smcpowers
4364219Smcpowers /* Call the CRYPTO_GENERATE_KEY ioctl */
4374219Smcpowers obj_gk.gk_session = session_p->k_session;
4384219Smcpowers obj_gk.gk_count = ulCount;
4394219Smcpowers obj_gk.gk_mechanism.cm_type = k_mech_type;
4404219Smcpowers obj_gk.gk_mechanism.cm_param = pMechanism->pParameter;
4414219Smcpowers obj_gk.gk_mechanism.cm_param_len = pMechanism->ulParameterLen;
4420Sstevel@tonic-gate
4434219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY,
4444219Smcpowers &obj_gk)) < 0) {
4454219Smcpowers if (errno != EINTR)
4464219Smcpowers break;
4474219Smcpowers }
4484219Smcpowers if (r < 0) {
4494219Smcpowers rv = CKR_FUNCTION_FAILED;
4504219Smcpowers } else {
4514219Smcpowers rv = crypto2pkcs11_error_number(obj_gk.gk_return_value);
4524219Smcpowers }
4534219Smcpowers
4544219Smcpowers free_object_attributes(obj_gk.gk_attributes, ulCount);
4554219Smcpowers
4564219Smcpowers if (rv != CKR_OK) {
4574219Smcpowers goto failed_exit;
4584219Smcpowers }
4590Sstevel@tonic-gate
4604219Smcpowers /* Get the value of the CKA_PRIVATE attribute. */
4614219Smcpowers rv = get_cka_private_value(session_p, obj_gk.gk_handle,
4624219Smcpowers &is_pri_obj);
4634219Smcpowers if (rv != CKR_OK) {
4644219Smcpowers goto failed_exit;
4654219Smcpowers }
4664219Smcpowers
4674219Smcpowers /*
4684219Smcpowers * Store the kernel object handle in the object wrapper and
4694219Smcpowers * initialize the library object.
4704219Smcpowers */
4714219Smcpowers new_objp->k_handle = obj_gk.gk_handle;
4724219Smcpowers new_objp->is_lib_obj = B_FALSE;
4734219Smcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
4744219Smcpowers new_objp->extra_attrlistp = NULL;
4754219Smcpowers
4764219Smcpowers if (is_pri_obj)
4774219Smcpowers new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
4784219Smcpowers else
4794219Smcpowers new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
4804219Smcpowers
4814219Smcpowers if (is_token_obj)
4824219Smcpowers new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
4834219Smcpowers else
4844219Smcpowers new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate
4870Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
4880Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate /*
4910Sstevel@tonic-gate * Add the new object to the slot's token object list if it is a
4920Sstevel@tonic-gate * a token object. Otherwise, add it to the session's object list.
4930Sstevel@tonic-gate */
4940Sstevel@tonic-gate if (is_token_obj) {
4950Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid];
4960Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot);
4970Sstevel@tonic-gate } else {
4980Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p);
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp;
5020Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
5030Sstevel@tonic-gate return (rv);
5040Sstevel@tonic-gate
5050Sstevel@tonic-gate failed_exit:
5060Sstevel@tonic-gate if (new_objp != NULL) {
5070Sstevel@tonic-gate (void) free(new_objp);
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
5110Sstevel@tonic-gate return (rv);
5120Sstevel@tonic-gate }
5130Sstevel@tonic-gate
5144219Smcpowers CK_RV
key_gen_rsa_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_pub_objp,kernel_object_t * new_pri_objp)5154219Smcpowers key_gen_rsa_by_value(CK_MECHANISM_PTR pMechanism,
5164219Smcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
5174219Smcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
5184219Smcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type,
5194219Smcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp)
5204219Smcpowers {
5214219Smcpowers crypto_nostore_generate_key_pair_t obj_nkp;
5224219Smcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL;
5234219Smcpowers CK_ATTRIBUTE_PTR priTemplate = NULL;
5244219Smcpowers CK_RV rv = CKR_OK;
5254219Smcpowers CK_BBOOL is_token_obj1 = FALSE;
5264219Smcpowers CK_BBOOL is_token_obj2 = FALSE;
5274219Smcpowers uint_t pub_attr_count, pri_attr_count;
5284219Smcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0;
5294219Smcpowers char public_modulus[512];
5304219Smcpowers char public_exponent[8];
5314219Smcpowers char private_exponent[512];
5324219Smcpowers char private_modulus[512];
5334219Smcpowers char prime_1[512];
5344219Smcpowers char prime_2[512];
5354219Smcpowers char exponent_1[512];
5364219Smcpowers char exponent_2[512];
5374219Smcpowers char coefficient[512];
5384219Smcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY;
5394219Smcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY;
5404219Smcpowers CK_ULONG key_type;
5414219Smcpowers CK_ULONG modulus_bytes;
5424219Smcpowers boolean_t has_class, has_key_type, has_pub_exponent;
5434219Smcpowers int n, r;
5444219Smcpowers
5454219Smcpowers obj_nkp.nkp_in_public_count = 0;
5464219Smcpowers obj_nkp.nkp_out_public_count = 0;
5474219Smcpowers obj_nkp.nkp_in_private_count = 0;
5484219Smcpowers obj_nkp.nkp_out_private_count = 0;
5494219Smcpowers
5504219Smcpowers /* modulus bits must be present when generating a RSA key pair */
5514219Smcpowers if (!attribute_in_template(CKA_MODULUS_BITS, pPublicKeyTemplate,
5524219Smcpowers ulPublicKeyAttributeCount)) {
5534219Smcpowers rv = CKR_TEMPLATE_INCOMPLETE;
5544219Smcpowers goto failed_exit;
5554219Smcpowers }
5564219Smcpowers
5574219Smcpowers modulus_bytes = get_modulus_bytes(pPublicKeyTemplate,
5584219Smcpowers ulPublicKeyAttributeCount);
5594219Smcpowers
5604219Smcpowers /*
5614219Smcpowers * Add CKA_MODULUS to the public template.
5624219Smcpowers * This attribute must not be in the template.
5634219Smcpowers */
5644219Smcpowers if (attribute_in_template(CKA_MODULUS, pPublicKeyTemplate,
5654219Smcpowers ulPublicKeyAttributeCount)) {
5664219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT;
5674219Smcpowers goto failed_exit;
5684219Smcpowers }
5694219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate,
5704219Smcpowers ulPublicKeyAttributeCount);
5714219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate,
5724219Smcpowers ulPublicKeyAttributeCount);
5734219Smcpowers has_pub_exponent = attribute_in_template(CKA_PUBLIC_EXPONENT,
5744219Smcpowers pPublicKeyTemplate, ulPublicKeyAttributeCount);
5754219Smcpowers
5764219Smcpowers pub_attr_count = ulPublicKeyAttributeCount + 1;
5774219Smcpowers if (!has_class)
5784219Smcpowers pub_attr_count++;
5794219Smcpowers if (!has_key_type)
5804219Smcpowers pub_attr_count++;
5814219Smcpowers if (!has_pub_exponent)
5824219Smcpowers pub_attr_count++;
5834219Smcpowers pubTemplate = grow_template(pPublicKeyTemplate,
5844219Smcpowers ulPublicKeyAttributeCount, pub_attr_count);
5854219Smcpowers if (pubTemplate == NULL) {
5864219Smcpowers rv = CKR_HOST_MEMORY;
5874219Smcpowers goto failed_exit;
5884219Smcpowers }
5894219Smcpowers
5904219Smcpowers n = ulPublicKeyAttributeCount;
5914219Smcpowers if (!has_class) {
5924219Smcpowers pubTemplate[n].type = CKA_CLASS;
5934219Smcpowers pubTemplate[n].pValue = (caddr_t)&pub_class;
5944219Smcpowers pubTemplate[n].ulValueLen = sizeof (pub_class);
5954219Smcpowers n++;
5964219Smcpowers }
5974219Smcpowers if (!has_key_type) {
5984219Smcpowers pubTemplate[n].type = CKA_KEY_TYPE;
5994219Smcpowers key_type = CKK_RSA;
6004219Smcpowers pubTemplate[n].pValue = (caddr_t)&key_type;
6014219Smcpowers pubTemplate[n].ulValueLen = sizeof (key_type);
6024219Smcpowers n++;
6034219Smcpowers }
6044219Smcpowers if (!has_pub_exponent) {
6054219Smcpowers pubTemplate[n].type = CKA_PUBLIC_EXPONENT;
6064219Smcpowers pubTemplate[n].pValue = (caddr_t)public_exponent;
6074219Smcpowers pubTemplate[n].ulValueLen = modulus_bytes;
6084219Smcpowers n++;
6094219Smcpowers pub_out_attr_count++;
6104219Smcpowers }
6114219Smcpowers pubTemplate[n].type = CKA_MODULUS;
6124219Smcpowers pubTemplate[n].pValue = (caddr_t)public_modulus;
6134219Smcpowers pubTemplate[n].ulValueLen = modulus_bytes;
6144219Smcpowers pub_out_attr_count++;
6154219Smcpowers
6164219Smcpowers rv = process_object_attributes(pubTemplate,
6174219Smcpowers pub_attr_count - pub_out_attr_count,
6184219Smcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1);
6194219Smcpowers if (rv != CKR_OK) {
6204219Smcpowers goto failed_exit;
6214219Smcpowers }
6224219Smcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count;
6234219Smcpowers
6244219Smcpowers rv = process_object_attributes(
6254219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
6264219Smcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes,
6274219Smcpowers &is_token_obj1);
6284219Smcpowers if (rv != CKR_OK) {
6294219Smcpowers goto failed_exit;
6304219Smcpowers }
6314219Smcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count;
6324219Smcpowers
6334219Smcpowers /*
6344219Smcpowers * Cannot create a token object with a READ-ONLY
6354219Smcpowers * session.
6364219Smcpowers */
6374219Smcpowers if (is_token_obj1 && session_p->ses_RO) {
6384219Smcpowers rv = CKR_SESSION_READ_ONLY;
6394219Smcpowers goto failed_exit;
6404219Smcpowers }
6414219Smcpowers
6424219Smcpowers /*
6434219Smcpowers * Add CKA_MODULUS and CKA_PRIVATE_EXPONENT
6444219Smcpowers * to the private template. These attributes
6454219Smcpowers * must not be in the template.
6464219Smcpowers */
6474219Smcpowers if (attribute_in_template(CKA_PRIVATE_EXPONENT,
6484219Smcpowers pPrivateKeyTemplate, ulPrivateKeyAttributeCount) ||
6494219Smcpowers attribute_in_template(CKA_MODULUS,
6504219Smcpowers pPrivateKeyTemplate, ulPrivateKeyAttributeCount)) {
6514219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT;
6524219Smcpowers goto failed_exit;
6534219Smcpowers }
6544219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate,
6554219Smcpowers ulPrivateKeyAttributeCount);
6564219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate,
6574219Smcpowers ulPrivateKeyAttributeCount);
6584219Smcpowers
6594219Smcpowers pri_attr_count = ulPrivateKeyAttributeCount + 7;
6604219Smcpowers if (!has_class)
6614219Smcpowers pri_attr_count++;
6624219Smcpowers if (!has_key_type)
6634219Smcpowers pri_attr_count++;
6644219Smcpowers
6654219Smcpowers /* allocate space for CKA_PUBLIC_EXPONENT */
6664219Smcpowers priTemplate = grow_template(pPrivateKeyTemplate,
6674219Smcpowers ulPrivateKeyAttributeCount, pri_attr_count + 1);
6684219Smcpowers if (priTemplate == NULL) {
6694219Smcpowers rv = CKR_HOST_MEMORY;
6704219Smcpowers goto failed_exit;
6714219Smcpowers }
6724219Smcpowers n = ulPrivateKeyAttributeCount;
6734219Smcpowers if (!has_class) {
6744219Smcpowers priTemplate[n].type = CKA_CLASS;
6754219Smcpowers priTemplate[n].pValue = (caddr_t)&pri_class;
6764219Smcpowers priTemplate[n].ulValueLen = sizeof (pri_class);
6774219Smcpowers n++;
6784219Smcpowers }
6794219Smcpowers if (!has_key_type) {
6804219Smcpowers priTemplate[n].type = CKA_KEY_TYPE;
6814219Smcpowers key_type = CKK_RSA;
6824219Smcpowers priTemplate[n].pValue = (caddr_t)&key_type;
6834219Smcpowers priTemplate[n].ulValueLen = sizeof (key_type);
6844219Smcpowers n++;
6854219Smcpowers }
6864219Smcpowers priTemplate[n].type = CKA_MODULUS;
6874219Smcpowers priTemplate[n].pValue = (caddr_t)private_modulus;
6884219Smcpowers priTemplate[n].ulValueLen = modulus_bytes;
6894219Smcpowers pri_out_attr_count++;
6904219Smcpowers
6914219Smcpowers n++;
6924219Smcpowers priTemplate[n].type = CKA_PRIVATE_EXPONENT;
6934219Smcpowers priTemplate[n].pValue = (caddr_t)private_exponent;
6944219Smcpowers priTemplate[n].ulValueLen = modulus_bytes;
6954219Smcpowers pri_out_attr_count++;
6964219Smcpowers
6974219Smcpowers n++;
6984219Smcpowers priTemplate[n].type = CKA_PRIME_1;
6994219Smcpowers priTemplate[n].pValue = (caddr_t)prime_1;
7004219Smcpowers priTemplate[n].ulValueLen = modulus_bytes/2;
7014219Smcpowers pri_out_attr_count++;
7024219Smcpowers
7034219Smcpowers n++;
7044219Smcpowers priTemplate[n].type = CKA_PRIME_2;
7054219Smcpowers priTemplate[n].pValue = (caddr_t)prime_2;
7064219Smcpowers priTemplate[n].ulValueLen = modulus_bytes/2;
7074219Smcpowers pri_out_attr_count++;
7084219Smcpowers
7094219Smcpowers n++;
7104219Smcpowers priTemplate[n].type = CKA_EXPONENT_1;
7114219Smcpowers priTemplate[n].pValue = (caddr_t)exponent_1;
7124219Smcpowers priTemplate[n].ulValueLen = modulus_bytes/2;
7134219Smcpowers pri_out_attr_count++;
7144219Smcpowers
7154219Smcpowers n++;
7164219Smcpowers priTemplate[n].type = CKA_EXPONENT_2;
7174219Smcpowers priTemplate[n].pValue = (caddr_t)exponent_2;
7184219Smcpowers priTemplate[n].ulValueLen = modulus_bytes/2;
7194219Smcpowers pri_out_attr_count++;
7204219Smcpowers
7214219Smcpowers n++;
7224219Smcpowers priTemplate[n].type = CKA_COEFFICIENT;
7234219Smcpowers priTemplate[n].pValue = (caddr_t)coefficient;
7244219Smcpowers priTemplate[n].ulValueLen = modulus_bytes/2;
7254219Smcpowers pri_out_attr_count++;
7264219Smcpowers
7274219Smcpowers rv = process_object_attributes(priTemplate,
7284219Smcpowers pri_attr_count - pri_out_attr_count,
7294219Smcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2);
7304219Smcpowers if (rv != CKR_OK) {
7314219Smcpowers goto failed_exit;
7324219Smcpowers }
7334219Smcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count;
7344219Smcpowers
7354219Smcpowers rv = process_object_attributes(
7364219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
7374219Smcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes,
7384219Smcpowers &is_token_obj2);
7394219Smcpowers if (rv != CKR_OK) {
7404219Smcpowers goto failed_exit;
7414219Smcpowers }
7424219Smcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count;
7434219Smcpowers
7444219Smcpowers /*
7454219Smcpowers * The public key and the private key need to contain the same
7464219Smcpowers * attribute values for CKA_TOKEN.
7474219Smcpowers */
7484219Smcpowers if (is_token_obj1 != is_token_obj2) {
7494219Smcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID;
7504219Smcpowers goto failed_exit;
7514219Smcpowers }
7524219Smcpowers
7534219Smcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
7544219Smcpowers obj_nkp.nkp_session = session_p-> k_session;
7554219Smcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type;
7564219Smcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter;
7574219Smcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen;
7584219Smcpowers
7594219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR,
7604219Smcpowers &obj_nkp)) < 0) {
7614219Smcpowers if (errno != EINTR)
7624219Smcpowers break;
7634219Smcpowers }
7644219Smcpowers if (r < 0) {
7654219Smcpowers rv = CKR_FUNCTION_FAILED;
7664219Smcpowers } else {
7674219Smcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value);
7684219Smcpowers }
7694219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
7704219Smcpowers &obj_nkp.nkp_in_public_count);
7714219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
7724219Smcpowers &obj_nkp.nkp_in_private_count);
7734219Smcpowers
7744219Smcpowers if (rv != CKR_OK) {
7754219Smcpowers goto failed_exit;
7764219Smcpowers }
7774219Smcpowers
7784219Smcpowers rv = get_object_attributes(
7794219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
7804219Smcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes);
7814219Smcpowers if (rv == CRYPTO_SUCCESS) {
7824219Smcpowers rv = get_object_attributes(
7834219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
7844219Smcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes);
7854219Smcpowers }
7864219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
7874219Smcpowers &obj_nkp.nkp_out_public_count);
7884219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
7894219Smcpowers &obj_nkp.nkp_out_private_count);
7904219Smcpowers if (rv != CRYPTO_SUCCESS) {
7914219Smcpowers goto failed_exit;
7924219Smcpowers }
7934219Smcpowers
7944219Smcpowers /* store generated modulus and public exponent */
7954219Smcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp,
7964219Smcpowers session_p, KERNEL_GEN_KEY);
7974219Smcpowers if (rv != CRYPTO_SUCCESS) {
7984219Smcpowers goto failed_exit;
7994219Smcpowers }
8004219Smcpowers
8014219Smcpowers /*
8024219Smcpowers * Copy CKA_PUBLIC_EXPONENT from the public template
8034219Smcpowers * to the private template.
8044219Smcpowers */
8054219Smcpowers rv = copy_attribute(CKA_PUBLIC_EXPONENT, pubTemplate,
8064219Smcpowers pub_attr_count, &priTemplate[pri_attr_count]);
8074219Smcpowers if (rv != CRYPTO_SUCCESS) {
8084219Smcpowers goto failed_exit;
8094219Smcpowers }
8104219Smcpowers
8114219Smcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 1, new_pri_objp,
8124219Smcpowers session_p, KERNEL_GEN_KEY);
8134219Smcpowers (void) free(priTemplate[pri_attr_count].pValue);
8144219Smcpowers if (rv != CRYPTO_SUCCESS) {
8154219Smcpowers goto failed_exit;
8164219Smcpowers }
8174219Smcpowers (void) free(pubTemplate);
8184219Smcpowers (void) free(priTemplate);
8194219Smcpowers
8204219Smcpowers new_pub_objp->is_lib_obj = B_TRUE;
8214219Smcpowers new_pri_objp->is_lib_obj = B_TRUE;
8224219Smcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
8234219Smcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
8244219Smcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
8254219Smcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
8264219Smcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
8274219Smcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
8284219Smcpowers return (CKR_OK);
8294219Smcpowers
8304219Smcpowers failed_exit:
8314219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
8324219Smcpowers &obj_nkp.nkp_in_public_count);
8334219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
8344219Smcpowers &obj_nkp.nkp_out_public_count);
8354219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
8364219Smcpowers &obj_nkp.nkp_in_private_count);
8374219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
8384219Smcpowers &obj_nkp.nkp_out_private_count);
8394219Smcpowers if (pubTemplate != NULL) {
8404219Smcpowers (void) free(pubTemplate);
8414219Smcpowers }
8424219Smcpowers if (priTemplate != NULL) {
8434219Smcpowers (void) free(priTemplate);
8444219Smcpowers }
8454219Smcpowers return (rv);
8464219Smcpowers }
8474219Smcpowers
8484219Smcpowers CK_RV
key_gen_dh_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_pub_objp,kernel_object_t * new_pri_objp)8494219Smcpowers key_gen_dh_by_value(CK_MECHANISM_PTR pMechanism,
8504219Smcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
8514219Smcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
8524219Smcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type,
8534219Smcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp)
8544219Smcpowers {
8554219Smcpowers crypto_nostore_generate_key_pair_t obj_nkp;
8564219Smcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL;
8574219Smcpowers CK_ATTRIBUTE_PTR priTemplate = NULL;
8584219Smcpowers CK_RV rv = CKR_OK;
8594219Smcpowers CK_BBOOL is_token_obj1 = FALSE;
8604219Smcpowers CK_BBOOL is_token_obj2 = FALSE;
8614219Smcpowers uint_t pub_attr_count, pri_attr_count;
8624219Smcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0;
8634219Smcpowers char public_value[256];
8644219Smcpowers char private_value[256];
8654219Smcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY;
8664219Smcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY;
8674219Smcpowers CK_ULONG key_type;
8684219Smcpowers boolean_t has_class, has_key_type;
8694219Smcpowers int n, r;
8704219Smcpowers
8714219Smcpowers obj_nkp.nkp_in_public_count = 0;
8724219Smcpowers obj_nkp.nkp_out_public_count = 0;
8734219Smcpowers obj_nkp.nkp_in_private_count = 0;
8744219Smcpowers obj_nkp.nkp_out_private_count = 0;
8754219Smcpowers
8764219Smcpowers /*
8774219Smcpowers * Add CKA_VALUE to the public template.
8784219Smcpowers * This attribute must not be in the template.
8794219Smcpowers */
8804219Smcpowers if (attribute_in_template(CKA_VALUE, pPublicKeyTemplate,
8814219Smcpowers ulPublicKeyAttributeCount)) {
8824219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT;
8834219Smcpowers goto failed_exit;
8844219Smcpowers }
8854219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate,
8864219Smcpowers ulPublicKeyAttributeCount);
8874219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate,
8884219Smcpowers ulPublicKeyAttributeCount);
8894219Smcpowers
8904219Smcpowers pub_attr_count = ulPublicKeyAttributeCount + 1;
8914219Smcpowers if (!has_class)
8924219Smcpowers pub_attr_count++;
8934219Smcpowers if (!has_key_type)
8944219Smcpowers pub_attr_count++;
8954219Smcpowers pubTemplate = grow_template(pPublicKeyTemplate,
8964219Smcpowers ulPublicKeyAttributeCount, pub_attr_count);
8974219Smcpowers if (pubTemplate == NULL) {
8984219Smcpowers rv = CKR_HOST_MEMORY;
8994219Smcpowers goto failed_exit;
9004219Smcpowers }
9014219Smcpowers
9024219Smcpowers n = ulPublicKeyAttributeCount;
9034219Smcpowers if (!has_class) {
9044219Smcpowers pubTemplate[n].type = CKA_CLASS;
9054219Smcpowers pubTemplate[n].pValue = (caddr_t)&pub_class;
9064219Smcpowers pubTemplate[n].ulValueLen = sizeof (pub_class);
9074219Smcpowers n++;
9084219Smcpowers }
9094219Smcpowers if (!has_key_type) {
9104219Smcpowers pubTemplate[n].type = CKA_KEY_TYPE;
9114219Smcpowers key_type = CKK_DH;
9124219Smcpowers pubTemplate[n].pValue = (caddr_t)&key_type;
9134219Smcpowers pubTemplate[n].ulValueLen = sizeof (key_type);
9144219Smcpowers n++;
9154219Smcpowers }
9164219Smcpowers pubTemplate[n].type = CKA_VALUE;
9174219Smcpowers pubTemplate[n].pValue = (caddr_t)public_value;
9184219Smcpowers pubTemplate[n].ulValueLen = sizeof (public_value);
9194219Smcpowers pub_out_attr_count++;
9204219Smcpowers
9214219Smcpowers rv = process_object_attributes(pubTemplate,
9224219Smcpowers pub_attr_count - pub_out_attr_count,
9234219Smcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1);
9244219Smcpowers if (rv != CKR_OK) {
9254219Smcpowers goto failed_exit;
9264219Smcpowers }
9274219Smcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count;
9284219Smcpowers
9294219Smcpowers rv = process_object_attributes(
9304219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
9314219Smcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes,
9324219Smcpowers &is_token_obj1);
9334219Smcpowers if (rv != CKR_OK) {
9344219Smcpowers goto failed_exit;
9354219Smcpowers }
9364219Smcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count;
9374219Smcpowers
9384219Smcpowers /*
9394219Smcpowers * Cannot create a token object with a READ-ONLY
9404219Smcpowers * session.
9414219Smcpowers */
9424219Smcpowers if (is_token_obj1 && session_p->ses_RO) {
9434219Smcpowers rv = CKR_SESSION_READ_ONLY;
9444219Smcpowers goto failed_exit;
9454219Smcpowers }
9464219Smcpowers
9474219Smcpowers /*
9484219Smcpowers * CKA_BASE, CKA_PRIME, and CKA_VALUE must not appear
9494219Smcpowers * in private template.
9504219Smcpowers */
9514219Smcpowers if (attribute_in_template(CKA_BASE, pPrivateKeyTemplate,
9524219Smcpowers ulPrivateKeyAttributeCount) ||
9534219Smcpowers attribute_in_template(CKA_PRIME, pPrivateKeyTemplate,
9544219Smcpowers ulPrivateKeyAttributeCount) ||
9554219Smcpowers attribute_in_template(CKA_VALUE, pPrivateKeyTemplate,
9564219Smcpowers ulPrivateKeyAttributeCount)) {
9574219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT;
9584219Smcpowers goto failed_exit;
9594219Smcpowers }
9604219Smcpowers
9614219Smcpowers if (attribute_in_template(CKA_VALUE, pPrivateKeyTemplate,
9624219Smcpowers ulPrivateKeyAttributeCount)) {
9634219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT;
9644219Smcpowers goto failed_exit;
9654219Smcpowers }
9664219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate,
9674219Smcpowers ulPrivateKeyAttributeCount);
9684219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate,
9694219Smcpowers ulPrivateKeyAttributeCount);
9704219Smcpowers
9714219Smcpowers pri_attr_count = ulPrivateKeyAttributeCount + 1;
9724219Smcpowers if (!has_class)
9734219Smcpowers pri_attr_count++;
9744219Smcpowers if (!has_key_type)
9754219Smcpowers pri_attr_count++;
9764219Smcpowers
9774219Smcpowers /* allocate space for CKA_BASE and CKA_PRIME */
9784219Smcpowers priTemplate = grow_template(pPrivateKeyTemplate,
9794219Smcpowers ulPrivateKeyAttributeCount, pri_attr_count + 2);
9804219Smcpowers if (priTemplate == NULL) {
9814219Smcpowers rv = CKR_HOST_MEMORY;
9824219Smcpowers goto failed_exit;
9834219Smcpowers }
9844219Smcpowers n = ulPrivateKeyAttributeCount;
9854219Smcpowers if (!has_class) {
9864219Smcpowers priTemplate[n].type = CKA_CLASS;
9874219Smcpowers priTemplate[n].pValue = (caddr_t)&pri_class;
9884219Smcpowers priTemplate[n].ulValueLen = sizeof (pri_class);
9894219Smcpowers n++;
9904219Smcpowers }
9914219Smcpowers if (!has_key_type) {
9924219Smcpowers priTemplate[n].type = CKA_KEY_TYPE;
9934219Smcpowers key_type = CKK_DH;
9944219Smcpowers priTemplate[n].pValue = (caddr_t)&key_type;
9954219Smcpowers priTemplate[n].ulValueLen = sizeof (key_type);
9964219Smcpowers n++;
9974219Smcpowers }
9984219Smcpowers priTemplate[n].type = CKA_VALUE;
9994219Smcpowers priTemplate[n].pValue = (caddr_t)private_value;
10004219Smcpowers priTemplate[n].ulValueLen = sizeof (private_value);
10014219Smcpowers pri_out_attr_count++;
10024219Smcpowers
10034219Smcpowers rv = process_object_attributes(priTemplate,
10044219Smcpowers pri_attr_count - pri_out_attr_count,
10054219Smcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2);
10064219Smcpowers if (rv != CKR_OK) {
10074219Smcpowers goto failed_exit;
10084219Smcpowers }
10094219Smcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count;
10104219Smcpowers
10114219Smcpowers rv = process_object_attributes(
10124219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
10134219Smcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes,
10144219Smcpowers &is_token_obj2);
10154219Smcpowers if (rv != CKR_OK) {
10164219Smcpowers goto failed_exit;
10174219Smcpowers }
10184219Smcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count;
10194219Smcpowers
10204219Smcpowers /*
10214219Smcpowers * The public key and the private key need to contain the same
10224219Smcpowers * attribute values for CKA_TOKEN.
10234219Smcpowers */
10244219Smcpowers if (is_token_obj1 != is_token_obj2) {
10254219Smcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID;
10264219Smcpowers goto failed_exit;
10274219Smcpowers }
10284219Smcpowers
10294219Smcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
10304219Smcpowers obj_nkp.nkp_session = session_p-> k_session;
10314219Smcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type;
10324219Smcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter;
10334219Smcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen;
10344219Smcpowers
10354219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR,
10364219Smcpowers &obj_nkp)) < 0) {
10374219Smcpowers if (errno != EINTR)
10384219Smcpowers break;
10394219Smcpowers }
10404219Smcpowers if (r < 0) {
10414219Smcpowers rv = CKR_FUNCTION_FAILED;
10424219Smcpowers } else {
10434219Smcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value);
10444219Smcpowers }
10454219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
10464219Smcpowers &obj_nkp.nkp_in_public_count);
10474219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
10484219Smcpowers &obj_nkp.nkp_in_private_count);
10494219Smcpowers
10504219Smcpowers if (rv != CKR_OK) {
10514219Smcpowers goto failed_exit;
10524219Smcpowers }
10534219Smcpowers
10544219Smcpowers rv = get_object_attributes(
10554219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
10564219Smcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes);
10574219Smcpowers if (rv == CRYPTO_SUCCESS) {
10584219Smcpowers rv = get_object_attributes(
10594219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
10604219Smcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes);
10614219Smcpowers }
10624219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
10634219Smcpowers &obj_nkp.nkp_out_public_count);
10644219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
10654219Smcpowers &obj_nkp.nkp_out_private_count);
10664219Smcpowers
10674219Smcpowers if (rv != CRYPTO_SUCCESS) {
10684219Smcpowers goto failed_exit;
10694219Smcpowers }
10704219Smcpowers
10714219Smcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp,
10724219Smcpowers session_p, KERNEL_GEN_KEY);
10734219Smcpowers if (rv != CRYPTO_SUCCESS) {
10744219Smcpowers goto failed_exit;
10754219Smcpowers }
10764219Smcpowers
10774219Smcpowers /*
10784219Smcpowers * Copy CKA_BASE and CKA_PRIME from the public template
10794219Smcpowers * to the private template.
10804219Smcpowers */
10814219Smcpowers rv = copy_attribute(CKA_BASE, pubTemplate, pub_attr_count,
10824219Smcpowers &priTemplate[pri_attr_count]);
10834219Smcpowers if (rv != CRYPTO_SUCCESS) {
10844219Smcpowers goto failed_exit;
10854219Smcpowers }
10864219Smcpowers rv = copy_attribute(CKA_PRIME, pubTemplate, pub_attr_count,
10874219Smcpowers &priTemplate[pri_attr_count + 1]);
10884219Smcpowers if (rv != CRYPTO_SUCCESS) {
10894219Smcpowers (void) free(priTemplate[pri_attr_count].pValue);
10904219Smcpowers goto failed_exit;
10914219Smcpowers }
10924219Smcpowers
10934219Smcpowers /* +2 to account for CKA_BASE and CKA_PRIME */
10944219Smcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 2,
10954219Smcpowers new_pri_objp, session_p, KERNEL_GEN_KEY);
10964219Smcpowers (void) free(priTemplate[pri_attr_count].pValue);
10974219Smcpowers (void) free(priTemplate[pri_attr_count + 1].pValue);
10984219Smcpowers if (rv != CRYPTO_SUCCESS) {
10994219Smcpowers goto failed_exit;
11004219Smcpowers }
11014219Smcpowers (void) free(pubTemplate);
11024219Smcpowers (void) free(priTemplate);
11034219Smcpowers
11044219Smcpowers new_pub_objp->is_lib_obj = B_TRUE;
11054219Smcpowers new_pri_objp->is_lib_obj = B_TRUE;
11064219Smcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
11074219Smcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
11084219Smcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
11094219Smcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
11104219Smcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
11114219Smcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
11124219Smcpowers return (CKR_OK);
11134219Smcpowers
11144219Smcpowers failed_exit:
11154219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
11164219Smcpowers &obj_nkp.nkp_in_public_count);
11174219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
11184219Smcpowers &obj_nkp.nkp_out_public_count);
11194219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
11204219Smcpowers &obj_nkp.nkp_in_private_count);
11214219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
11224219Smcpowers &obj_nkp.nkp_out_private_count);
11234219Smcpowers if (pubTemplate != NULL) {
11244219Smcpowers (void) free(pubTemplate);
11254219Smcpowers }
11264219Smcpowers if (priTemplate != NULL) {
11274219Smcpowers (void) free(priTemplate);
11284219Smcpowers }
11294219Smcpowers return (rv);
11304219Smcpowers }
11314219Smcpowers
11324219Smcpowers CK_RV
key_gen_ec_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_pub_objp,kernel_object_t * new_pri_objp)11334219Smcpowers key_gen_ec_by_value(CK_MECHANISM_PTR pMechanism,
11344219Smcpowers CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
11354219Smcpowers CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
11364219Smcpowers kernel_session_t *session_p, crypto_mech_type_t k_mech_type,
11374219Smcpowers kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp)
11384219Smcpowers {
11394219Smcpowers crypto_nostore_generate_key_pair_t obj_nkp;
11404219Smcpowers CK_ATTRIBUTE_PTR pubTemplate = NULL;
11414219Smcpowers CK_ATTRIBUTE_PTR priTemplate = NULL;
11424219Smcpowers CK_RV rv = CKR_OK;
11434219Smcpowers CK_BBOOL is_token_obj1 = FALSE;
11444219Smcpowers CK_BBOOL is_token_obj2 = FALSE;
11454219Smcpowers uint_t pub_attr_count, pri_attr_count;
11464219Smcpowers uint_t pub_out_attr_count = 0, pri_out_attr_count = 0;
11475697Smcpowers char value[EC_MAX_VALUE_LEN];
11485697Smcpowers char point[EC_MAX_POINT_LEN];
11494219Smcpowers CK_ULONG pub_class = CKO_PUBLIC_KEY;
11504219Smcpowers CK_ULONG pri_class = CKO_PRIVATE_KEY;
11514219Smcpowers CK_ULONG key_type;
11524219Smcpowers boolean_t has_class, has_key_type;
11534219Smcpowers int n, r;
11544219Smcpowers
11554219Smcpowers obj_nkp.nkp_in_public_count = 0;
11564219Smcpowers obj_nkp.nkp_out_public_count = 0;
11574219Smcpowers obj_nkp.nkp_in_private_count = 0;
11584219Smcpowers obj_nkp.nkp_out_private_count = 0;
11594219Smcpowers
11604219Smcpowers /*
11614219Smcpowers * Add CKA_EC_POINT to the public template.
11624219Smcpowers * This is the generated value Q. This attribute
11634219Smcpowers * must not be in the template.
11644219Smcpowers */
11654219Smcpowers if (attribute_in_template(CKA_EC_POINT, pPublicKeyTemplate,
11664219Smcpowers ulPublicKeyAttributeCount)) {
11674219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT;
11684219Smcpowers goto failed_exit;
11694219Smcpowers }
11704219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate,
11714219Smcpowers ulPublicKeyAttributeCount);
11724219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate,
11734219Smcpowers ulPublicKeyAttributeCount);
11744219Smcpowers
11754219Smcpowers pub_attr_count = ulPublicKeyAttributeCount + 1;
11764219Smcpowers if (!has_class)
11774219Smcpowers pub_attr_count++;
11784219Smcpowers if (!has_key_type)
11794219Smcpowers pub_attr_count++;
11804219Smcpowers pubTemplate = grow_template(pPublicKeyTemplate,
11814219Smcpowers ulPublicKeyAttributeCount, pub_attr_count);
11824219Smcpowers if (pubTemplate == NULL) {
11834219Smcpowers rv = CKR_HOST_MEMORY;
11844219Smcpowers goto failed_exit;
11854219Smcpowers }
11864219Smcpowers
11874219Smcpowers n = ulPublicKeyAttributeCount;
11884219Smcpowers if (!has_class) {
11894219Smcpowers pubTemplate[n].type = CKA_CLASS;
11904219Smcpowers pubTemplate[n].pValue = (caddr_t)&pub_class;
11914219Smcpowers pubTemplate[n].ulValueLen = sizeof (pub_class);
11924219Smcpowers n++;
11934219Smcpowers }
11944219Smcpowers if (!has_key_type) {
11954219Smcpowers pubTemplate[n].type = CKA_KEY_TYPE;
11964219Smcpowers key_type = CKK_EC;
11974219Smcpowers pubTemplate[n].pValue = (caddr_t)&key_type;
11984219Smcpowers pubTemplate[n].ulValueLen = sizeof (key_type);
11994219Smcpowers n++;
12004219Smcpowers }
12014219Smcpowers pubTemplate[n].type = CKA_EC_POINT;
12024219Smcpowers pubTemplate[n].pValue = (caddr_t)point;
12034219Smcpowers pubTemplate[n].ulValueLen = sizeof (point);
12044219Smcpowers pub_out_attr_count++;
12054219Smcpowers
12064219Smcpowers rv = process_object_attributes(pubTemplate,
12074219Smcpowers pub_attr_count - pub_out_attr_count,
12084219Smcpowers &obj_nkp.nkp_in_public_attributes, &is_token_obj1);
12094219Smcpowers if (rv != CKR_OK) {
12104219Smcpowers goto failed_exit;
12114219Smcpowers }
12124219Smcpowers obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count;
12134219Smcpowers
12144219Smcpowers rv = process_object_attributes(
12154219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
12164219Smcpowers pub_out_attr_count, &obj_nkp.nkp_out_public_attributes,
12174219Smcpowers &is_token_obj1);
12184219Smcpowers if (rv != CKR_OK) {
12194219Smcpowers goto failed_exit;
12204219Smcpowers }
12214219Smcpowers obj_nkp.nkp_out_public_count = pub_out_attr_count;
12224219Smcpowers
12234219Smcpowers /*
12244219Smcpowers * Cannot create a token object with a READ-ONLY
12254219Smcpowers * session.
12264219Smcpowers */
12274219Smcpowers if (is_token_obj1 && session_p->ses_RO) {
12284219Smcpowers rv = CKR_SESSION_READ_ONLY;
12294219Smcpowers goto failed_exit;
12304219Smcpowers }
12314219Smcpowers
12324219Smcpowers /*
12334219Smcpowers * CKA_EC_PARAMS and CKA_VALUE must not appear in
12344219Smcpowers * private template.
12354219Smcpowers */
12364219Smcpowers if (attribute_in_template(CKA_EC_PARAMS, pPrivateKeyTemplate,
12374219Smcpowers ulPrivateKeyAttributeCount) ||
12384219Smcpowers attribute_in_template(CKA_VALUE, pPrivateKeyTemplate,
12394219Smcpowers ulPrivateKeyAttributeCount)) {
12404219Smcpowers rv = CKR_TEMPLATE_INCONSISTENT;
12414219Smcpowers goto failed_exit;
12424219Smcpowers }
12434219Smcpowers has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate,
12444219Smcpowers ulPrivateKeyAttributeCount);
12454219Smcpowers has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate,
12464219Smcpowers ulPrivateKeyAttributeCount);
12474219Smcpowers
12484219Smcpowers pri_attr_count = ulPrivateKeyAttributeCount + 1;
12494219Smcpowers if (!has_class)
12504219Smcpowers pri_attr_count++;
12514219Smcpowers if (!has_key_type)
12524219Smcpowers pri_attr_count++;
12534219Smcpowers
12544219Smcpowers /* allocate space for CKA_EC_PARAMS */
12554219Smcpowers priTemplate = grow_template(pPrivateKeyTemplate,
12564219Smcpowers ulPrivateKeyAttributeCount, pri_attr_count + 1);
12574219Smcpowers if (priTemplate == NULL) {
12584219Smcpowers rv = CKR_HOST_MEMORY;
12594219Smcpowers goto failed_exit;
12604219Smcpowers }
12614219Smcpowers n = ulPrivateKeyAttributeCount;
12624219Smcpowers if (!has_class) {
12634219Smcpowers priTemplate[n].type = CKA_CLASS;
12644219Smcpowers priTemplate[n].pValue = (caddr_t)&pri_class;
12654219Smcpowers priTemplate[n].ulValueLen = sizeof (pri_class);
12664219Smcpowers n++;
12674219Smcpowers }
12684219Smcpowers if (!has_key_type) {
12694219Smcpowers priTemplate[n].type = CKA_KEY_TYPE;
12704219Smcpowers key_type = CKK_EC;
12714219Smcpowers priTemplate[n].pValue = (caddr_t)&key_type;
12724219Smcpowers priTemplate[n].ulValueLen = sizeof (key_type);
12734219Smcpowers n++;
12744219Smcpowers }
12754219Smcpowers priTemplate[n].type = CKA_VALUE;
12764219Smcpowers priTemplate[n].pValue = (caddr_t)value;
12774219Smcpowers priTemplate[n].ulValueLen = sizeof (value);
12784219Smcpowers pri_out_attr_count++;
12794219Smcpowers
12804219Smcpowers rv = process_object_attributes(priTemplate,
12814219Smcpowers pri_attr_count - pri_out_attr_count,
12824219Smcpowers &obj_nkp.nkp_in_private_attributes, &is_token_obj2);
12834219Smcpowers if (rv != CKR_OK) {
12844219Smcpowers goto failed_exit;
12854219Smcpowers }
12864219Smcpowers obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count;
12874219Smcpowers
12884219Smcpowers rv = process_object_attributes(
12894219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
12904219Smcpowers pri_out_attr_count, &obj_nkp.nkp_out_private_attributes,
12914219Smcpowers &is_token_obj2);
12924219Smcpowers if (rv != CKR_OK) {
12934219Smcpowers goto failed_exit;
12944219Smcpowers }
12954219Smcpowers obj_nkp.nkp_out_private_count = pri_out_attr_count;
12964219Smcpowers
12974219Smcpowers /*
12984219Smcpowers * The public key and the private key need to contain the same
12994219Smcpowers * attribute values for CKA_TOKEN.
13004219Smcpowers */
13014219Smcpowers if (is_token_obj1 != is_token_obj2) {
13024219Smcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID;
13034219Smcpowers goto failed_exit;
13044219Smcpowers }
13054219Smcpowers
13064219Smcpowers /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
13074219Smcpowers obj_nkp.nkp_session = session_p-> k_session;
13084219Smcpowers obj_nkp.nkp_mechanism.cm_type = k_mech_type;
13094219Smcpowers obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter;
13104219Smcpowers obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen;
13114219Smcpowers
13124219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR,
13134219Smcpowers &obj_nkp)) < 0) {
13144219Smcpowers if (errno != EINTR)
13154219Smcpowers break;
13164219Smcpowers }
13174219Smcpowers if (r < 0) {
13184219Smcpowers rv = CKR_FUNCTION_FAILED;
13194219Smcpowers } else {
13204219Smcpowers rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value);
13214219Smcpowers }
13224219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
13234219Smcpowers &obj_nkp.nkp_in_public_count);
13244219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
13254219Smcpowers &obj_nkp.nkp_in_private_count);
13264219Smcpowers
13274219Smcpowers if (rv != CKR_OK) {
13284219Smcpowers goto failed_exit;
13294219Smcpowers }
13304219Smcpowers
13314219Smcpowers rv = get_object_attributes(
13324219Smcpowers &pubTemplate[pub_attr_count - pub_out_attr_count],
13334219Smcpowers pub_out_attr_count, obj_nkp.nkp_out_public_attributes);
13344219Smcpowers if (rv == CRYPTO_SUCCESS) {
13354219Smcpowers rv = get_object_attributes(
13364219Smcpowers &priTemplate[pri_attr_count - pri_out_attr_count],
13374219Smcpowers pri_out_attr_count, obj_nkp.nkp_out_private_attributes);
13384219Smcpowers }
13394219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
13404219Smcpowers &obj_nkp.nkp_out_public_count);
13414219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
13424219Smcpowers &obj_nkp.nkp_out_private_count);
13434219Smcpowers if (rv != CRYPTO_SUCCESS) {
13444219Smcpowers goto failed_exit;
13454219Smcpowers }
13464219Smcpowers
13474219Smcpowers rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp,
13484219Smcpowers session_p, KERNEL_GEN_KEY);
13494219Smcpowers if (rv != CRYPTO_SUCCESS) {
13504219Smcpowers goto failed_exit;
13514219Smcpowers }
13524219Smcpowers
13534219Smcpowers /*
13544219Smcpowers * Copy CKA_EC_PARAMS from the public template to the
13554219Smcpowers * private template.
13564219Smcpowers */
13574219Smcpowers rv = copy_attribute(CKA_EC_PARAMS, pubTemplate, pub_attr_count,
13584219Smcpowers &priTemplate[pri_attr_count]);
13594219Smcpowers if (rv != CRYPTO_SUCCESS) {
13604219Smcpowers goto failed_exit;
13614219Smcpowers }
13624219Smcpowers
13634219Smcpowers /* +1 to account for CKA_EC_PARAMS */
13644219Smcpowers rv = kernel_build_object(priTemplate, pri_attr_count + 1,
13654219Smcpowers new_pri_objp, session_p, KERNEL_GEN_KEY);
13664219Smcpowers (void) free(priTemplate[pri_attr_count].pValue);
13674219Smcpowers if (rv != CRYPTO_SUCCESS) {
13684219Smcpowers goto failed_exit;
13694219Smcpowers }
13704219Smcpowers (void) free(pubTemplate);
13714219Smcpowers (void) free(priTemplate);
13724219Smcpowers
13734219Smcpowers new_pub_objp->is_lib_obj = B_TRUE;
13744219Smcpowers new_pri_objp->is_lib_obj = B_TRUE;
13754219Smcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
13764219Smcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
13774219Smcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
13784219Smcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
13794219Smcpowers (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
13804219Smcpowers new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
13814219Smcpowers return (CKR_OK);
13824219Smcpowers
13834219Smcpowers failed_exit:
13844219Smcpowers free_attributes(obj_nkp.nkp_in_public_attributes,
13854219Smcpowers &obj_nkp.nkp_in_public_count);
13864219Smcpowers free_attributes(obj_nkp.nkp_out_public_attributes,
13874219Smcpowers &obj_nkp.nkp_out_public_count);
13884219Smcpowers free_attributes(obj_nkp.nkp_in_private_attributes,
13894219Smcpowers &obj_nkp.nkp_in_private_count);
13904219Smcpowers free_attributes(obj_nkp.nkp_out_private_attributes,
13914219Smcpowers &obj_nkp.nkp_out_private_count);
13924219Smcpowers if (pubTemplate != NULL) {
13934219Smcpowers (void) free(pubTemplate);
13944219Smcpowers }
13954219Smcpowers if (priTemplate != NULL) {
13964219Smcpowers (void) free(priTemplate);
13974219Smcpowers }
13984219Smcpowers return (rv);
13994219Smcpowers }
14000Sstevel@tonic-gate
14010Sstevel@tonic-gate CK_RV
C_GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey)14020Sstevel@tonic-gate C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
14030Sstevel@tonic-gate CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
14040Sstevel@tonic-gate CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
14050Sstevel@tonic-gate CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
14060Sstevel@tonic-gate {
14070Sstevel@tonic-gate CK_RV rv = CKR_OK;
14080Sstevel@tonic-gate kernel_session_t *session_p;
14090Sstevel@tonic-gate kernel_object_t *new_pub_objp = NULL;
14100Sstevel@tonic-gate kernel_object_t *new_pri_objp = NULL;
14110Sstevel@tonic-gate kernel_slot_t *pslot;
14120Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE;
14130Sstevel@tonic-gate CK_BBOOL is_pri_obj1;
14140Sstevel@tonic-gate CK_BBOOL is_pri_obj2;
14150Sstevel@tonic-gate CK_BBOOL is_token_obj1 = FALSE;
14160Sstevel@tonic-gate CK_BBOOL is_token_obj2 = FALSE;
14170Sstevel@tonic-gate crypto_mech_type_t k_mech_type;
14180Sstevel@tonic-gate int r;
14194219Smcpowers CK_RV (*func)(CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG,
14204219Smcpowers CK_ATTRIBUTE_PTR, CK_ULONG, kernel_session_t *, crypto_mech_type_t,
14214219Smcpowers kernel_object_t *, kernel_object_t *);
14220Sstevel@tonic-gate
14230Sstevel@tonic-gate if (!kernel_initialized)
14240Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
14250Sstevel@tonic-gate
14260Sstevel@tonic-gate /* Obtain the session pointer. */
14270Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
14280Sstevel@tonic-gate if (rv != CKR_OK)
14290Sstevel@tonic-gate return (rv);
14300Sstevel@tonic-gate
14310Sstevel@tonic-gate if ((pMechanism == NULL) || (phPublicKey == NULL) ||
14320Sstevel@tonic-gate (phPrivateKey == NULL)) {
14330Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
14340Sstevel@tonic-gate goto failed_exit;
14350Sstevel@tonic-gate }
14360Sstevel@tonic-gate
14370Sstevel@tonic-gate if ((pPublicKeyTemplate == NULL) && (ulPublicKeyAttributeCount != 0)) {
14380Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
14390Sstevel@tonic-gate goto failed_exit;
14400Sstevel@tonic-gate }
14410Sstevel@tonic-gate
14420Sstevel@tonic-gate if ((pPrivateKeyTemplate == NULL) &&
14430Sstevel@tonic-gate (ulPrivateKeyAttributeCount != 0)) {
14440Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
14450Sstevel@tonic-gate goto failed_exit;
14460Sstevel@tonic-gate }
14470Sstevel@tonic-gate
14480Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */
14490Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
14500Sstevel@tonic-gate if (rv != CKR_OK) {
14510Sstevel@tonic-gate goto failed_exit;
14520Sstevel@tonic-gate }
14530Sstevel@tonic-gate
14540Sstevel@tonic-gate /* Create an object wrapper for the public key */
14550Sstevel@tonic-gate new_pub_objp = calloc(1, sizeof (kernel_object_t));
14560Sstevel@tonic-gate if (new_pub_objp == NULL) {
14570Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
14580Sstevel@tonic-gate goto failed_exit;
14590Sstevel@tonic-gate }
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate /* Create an object wrapper for the private key. */
14620Sstevel@tonic-gate new_pri_objp = calloc(1, sizeof (kernel_object_t));
14630Sstevel@tonic-gate if (new_pri_objp == NULL) {
14640Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
14650Sstevel@tonic-gate goto failed_exit;
14660Sstevel@tonic-gate }
14670Sstevel@tonic-gate
14684219Smcpowers /*
14694219Smcpowers * Special Case: if token does not support object creation,
14704219Smcpowers * but does support key generation by value, then create a session
14714219Smcpowers * object and initialize with values returned by token.
14724219Smcpowers */
14734219Smcpowers pslot = slot_table[session_p->ses_slotid];
14744219Smcpowers if (!pslot->sl_func_list.fl_object_create) {
14754219Smcpowers switch (pMechanism->mechanism) {
14764219Smcpowers case CKM_RSA_PKCS_KEY_PAIR_GEN:
14774219Smcpowers func = key_gen_rsa_by_value;
14784219Smcpowers break;
14794219Smcpowers
14804219Smcpowers case CKM_DH_PKCS_KEY_PAIR_GEN:
14814219Smcpowers func = key_gen_dh_by_value;
14824219Smcpowers break;
14834219Smcpowers
14844219Smcpowers case CKM_EC_KEY_PAIR_GEN:
14854219Smcpowers func = key_gen_ec_by_value;
14864219Smcpowers break;
14870Sstevel@tonic-gate
14884219Smcpowers default:
14894219Smcpowers rv = CKR_MECHANISM_INVALID;
14904219Smcpowers goto failed_exit;
14914219Smcpowers }
14924219Smcpowers rv = (*func)(pMechanism, pPublicKeyTemplate,
14934219Smcpowers ulPublicKeyAttributeCount, pPrivateKeyTemplate,
14944219Smcpowers ulPrivateKeyAttributeCount, session_p, k_mech_type,
14954219Smcpowers new_pub_objp, new_pri_objp);
14964219Smcpowers if (rv != CKR_OK)
14974219Smcpowers goto failed_exit;
14984219Smcpowers } else {
14994219Smcpowers crypto_object_generate_key_pair_t obj_kp;
15004219Smcpowers
15014219Smcpowers /* Process the public key attributes. */
15024219Smcpowers rv = process_object_attributes(pPublicKeyTemplate,
15034219Smcpowers ulPublicKeyAttributeCount, &obj_kp.kp_public_attributes,
15044219Smcpowers &is_token_obj1);
15054219Smcpowers if (rv != CKR_OK) {
15064219Smcpowers goto failed_exit;
15074219Smcpowers }
15080Sstevel@tonic-gate
15094219Smcpowers /* Cannot create a token object with a READ-ONLY session. */
15104219Smcpowers if (is_token_obj1 && session_p->ses_RO) {
15114219Smcpowers free_object_attributes(obj_kp.kp_public_attributes,
15124219Smcpowers ulPublicKeyAttributeCount);
15134219Smcpowers rv = CKR_SESSION_READ_ONLY;
15144219Smcpowers goto failed_exit;
15154219Smcpowers }
15164219Smcpowers
15174219Smcpowers /* Process the private key attributes. */
15184219Smcpowers rv = process_object_attributes(pPrivateKeyTemplate,
15194219Smcpowers ulPrivateKeyAttributeCount, &obj_kp.kp_private_attributes,
15204219Smcpowers &is_token_obj2);
15214219Smcpowers if (rv != CKR_OK) {
15224219Smcpowers free_object_attributes(obj_kp.kp_public_attributes,
15234219Smcpowers ulPublicKeyAttributeCount);
15244219Smcpowers goto failed_exit;
15254219Smcpowers }
15260Sstevel@tonic-gate
15274219Smcpowers /*
15284219Smcpowers * The public key and the private key need to contain the same
15294219Smcpowers * attribute values for CKA_TOKEN.
15304219Smcpowers */
15314219Smcpowers if (is_token_obj1 != is_token_obj2) {
15324219Smcpowers free_object_attributes(obj_kp.kp_public_attributes,
15334219Smcpowers ulPublicKeyAttributeCount);
15344219Smcpowers free_object_attributes(obj_kp.kp_private_attributes,
15354219Smcpowers ulPrivateKeyAttributeCount);
15364219Smcpowers rv = CKR_ATTRIBUTE_VALUE_INVALID;
15374219Smcpowers goto failed_exit;
15384219Smcpowers }
15394219Smcpowers
15404219Smcpowers /* Call the CRYPTO_GENERATE_KEY_PAIR ioctl. */
15414219Smcpowers obj_kp.kp_session = session_p-> k_session;
15424219Smcpowers obj_kp.kp_mechanism.cm_type = k_mech_type;
15434219Smcpowers obj_kp.kp_mechanism.cm_param = pMechanism->pParameter;
15444219Smcpowers obj_kp.kp_mechanism.cm_param_len = pMechanism->ulParameterLen;
15454219Smcpowers obj_kp.kp_public_count = ulPublicKeyAttributeCount;
15464219Smcpowers obj_kp.kp_private_count = ulPrivateKeyAttributeCount;
15474219Smcpowers
15484219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY_PAIR,
15494219Smcpowers &obj_kp)) < 0) {
15504219Smcpowers if (errno != EINTR)
15514219Smcpowers break;
15524219Smcpowers }
15534219Smcpowers if (r < 0) {
15544219Smcpowers rv = CKR_FUNCTION_FAILED;
15554219Smcpowers } else {
15564219Smcpowers rv = crypto2pkcs11_error_number(obj_kp.kp_return_value);
15574219Smcpowers }
15580Sstevel@tonic-gate free_object_attributes(obj_kp.kp_public_attributes,
15590Sstevel@tonic-gate ulPublicKeyAttributeCount);
15600Sstevel@tonic-gate free_object_attributes(obj_kp.kp_private_attributes,
15610Sstevel@tonic-gate ulPrivateKeyAttributeCount);
15624219Smcpowers
15634219Smcpowers if (rv != CKR_OK)
15644219Smcpowers goto failed_exit;
15654219Smcpowers
15664219Smcpowers /* Get the CKA_PRIVATE value for the key pair. */
15674219Smcpowers rv = get_cka_private_value(session_p, obj_kp.kp_public_handle,
15684219Smcpowers &is_pri_obj1);
15694219Smcpowers if (rv != CKR_OK) {
15704219Smcpowers goto failed_exit;
15714219Smcpowers }
15720Sstevel@tonic-gate
15734219Smcpowers rv = get_cka_private_value(session_p, obj_kp.kp_private_handle,
15744219Smcpowers &is_pri_obj2);
15754219Smcpowers if (rv != CKR_OK) {
15764219Smcpowers goto failed_exit;
15774219Smcpowers }
15784219Smcpowers
15794219Smcpowers /*
15804219Smcpowers * Store the kernel public key handle into the public key
15814219Smcpowers * object and finish the public key object initialization.
15824219Smcpowers */
15834219Smcpowers new_pub_objp->is_lib_obj = B_FALSE;
15844219Smcpowers new_pub_objp->k_handle = obj_kp.kp_public_handle;
15854219Smcpowers new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
15864219Smcpowers new_pub_objp->extra_attrlistp = NULL;
15870Sstevel@tonic-gate
15884219Smcpowers if (is_pri_obj1)
15894219Smcpowers new_pub_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
15904219Smcpowers else
15914219Smcpowers new_pub_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
15920Sstevel@tonic-gate
15934219Smcpowers if (is_token_obj1)
15944219Smcpowers new_pub_objp->bool_attr_mask |= TOKEN_BOOL_ON;
15954219Smcpowers else
15964219Smcpowers new_pub_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
15974219Smcpowers
15984219Smcpowers (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
15994219Smcpowers new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
16000Sstevel@tonic-gate
16014219Smcpowers /*
16024219Smcpowers * Store the kernel private key handle into the private key
16034219Smcpowers * object and finish the private key object initialization.
16044219Smcpowers */
16054219Smcpowers new_pri_objp->is_lib_obj = B_FALSE;
16064219Smcpowers new_pri_objp->k_handle = obj_kp.kp_private_handle;
16074219Smcpowers new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
16084219Smcpowers new_pri_objp->extra_attrlistp = NULL;
16090Sstevel@tonic-gate
16104219Smcpowers if (is_pri_obj2)
16114219Smcpowers new_pri_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
16124219Smcpowers else
16134219Smcpowers new_pri_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
16140Sstevel@tonic-gate
16154219Smcpowers if (is_token_obj2)
16164219Smcpowers new_pri_objp->bool_attr_mask |= TOKEN_BOOL_ON;
16174219Smcpowers else
16184219Smcpowers new_pri_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
16194219Smcpowers
16200Sstevel@tonic-gate }
16210Sstevel@tonic-gate (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
16220Sstevel@tonic-gate new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
16230Sstevel@tonic-gate
16240Sstevel@tonic-gate /*
16250Sstevel@tonic-gate * Add the new pub/pri objects to the slot's token list if they are
16260Sstevel@tonic-gate * token objects. Otherwise, add them to the session's object list.
16270Sstevel@tonic-gate */
16280Sstevel@tonic-gate if (is_token_obj1) { /* is_token_obj1 == is_token_obj2 */
16290Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid];
16300Sstevel@tonic-gate kernel_add_token_object_to_slot(new_pub_objp, pslot);
16310Sstevel@tonic-gate kernel_add_token_object_to_slot(new_pri_objp, pslot);
16320Sstevel@tonic-gate } else {
16330Sstevel@tonic-gate kernel_add_object_to_session(new_pub_objp, session_p);
16340Sstevel@tonic-gate kernel_add_object_to_session(new_pri_objp, session_p);
16350Sstevel@tonic-gate }
16360Sstevel@tonic-gate
16370Sstevel@tonic-gate *phPublicKey = (CK_OBJECT_HANDLE)new_pub_objp;
16380Sstevel@tonic-gate *phPrivateKey = (CK_OBJECT_HANDLE)new_pri_objp;
16390Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
16400Sstevel@tonic-gate return (rv);
16410Sstevel@tonic-gate
16420Sstevel@tonic-gate failed_exit:
16430Sstevel@tonic-gate if (new_pub_objp != NULL) {
16440Sstevel@tonic-gate (void) free(new_pub_objp);
16450Sstevel@tonic-gate }
16460Sstevel@tonic-gate if (new_pri_objp != NULL) {
16470Sstevel@tonic-gate (void) free(new_pri_objp);
16480Sstevel@tonic-gate }
16490Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
16500Sstevel@tonic-gate return (rv);
16510Sstevel@tonic-gate }
16520Sstevel@tonic-gate
16530Sstevel@tonic-gate
16540Sstevel@tonic-gate CK_RV
C_WrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hWrappingKey,CK_OBJECT_HANDLE hKey,CK_BYTE_PTR pWrappedKey,CK_ULONG_PTR pulWrappedKeyLen)16550Sstevel@tonic-gate C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
16560Sstevel@tonic-gate CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
16570Sstevel@tonic-gate CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
16580Sstevel@tonic-gate {
16590Sstevel@tonic-gate CK_RV rv = CKR_OK;
16600Sstevel@tonic-gate kernel_session_t *session_p;
16610Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE;
16620Sstevel@tonic-gate kernel_object_t *wrappingkey_p;
16630Sstevel@tonic-gate kernel_object_t *key_p;
16640Sstevel@tonic-gate crypto_mech_type_t k_mech_type;
16650Sstevel@tonic-gate crypto_object_wrap_key_t obj_wrapkey;
16660Sstevel@tonic-gate int r;
16670Sstevel@tonic-gate
16680Sstevel@tonic-gate if (!kernel_initialized)
16690Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
16700Sstevel@tonic-gate
16710Sstevel@tonic-gate if (pulWrappedKeyLen == NULL || pMechanism == NULL) {
16720Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
16730Sstevel@tonic-gate }
16740Sstevel@tonic-gate
16750Sstevel@tonic-gate /*
16760Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session
16770Sstevel@tonic-gate * reference count.
16780Sstevel@tonic-gate */
16790Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
16800Sstevel@tonic-gate if (rv != CKR_OK)
16810Sstevel@tonic-gate return (rv);
16820Sstevel@tonic-gate
16830Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */
16840Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
16850Sstevel@tonic-gate if (rv != CKR_OK) {
16860Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
16870Sstevel@tonic-gate return (rv);
16880Sstevel@tonic-gate }
16890Sstevel@tonic-gate
16900Sstevel@tonic-gate /* Obtain the wrapping key object pointer. */
16910Sstevel@tonic-gate HANDLE2OBJECT(hWrappingKey, wrappingkey_p, rv);
16920Sstevel@tonic-gate if (rv != CKR_OK) {
16930Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
16940Sstevel@tonic-gate return (rv);
16950Sstevel@tonic-gate }
16960Sstevel@tonic-gate
16970Sstevel@tonic-gate /* Obtain the to_be_wrapped key object pointer. */
16980Sstevel@tonic-gate HANDLE2OBJECT(hKey, key_p, rv);
16990Sstevel@tonic-gate if (rv != CKR_OK) {
1700214Smcpowers OBJ_REFRELE(wrappingkey_p);
17010Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
17020Sstevel@tonic-gate return (rv);
17030Sstevel@tonic-gate }
17040Sstevel@tonic-gate
17050Sstevel@tonic-gate /* Make the CRYPTO_OBJECT_WRAP_KEY ioctl call. */
17060Sstevel@tonic-gate obj_wrapkey.wk_session = session_p->k_session;
17070Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_type = k_mech_type;
17080Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_param = pMechanism->pParameter;
17090Sstevel@tonic-gate obj_wrapkey.wk_mechanism.cm_param_len = pMechanism->ulParameterLen;
17100Sstevel@tonic-gate obj_wrapkey.wk_wrapping_key.ck_format = CRYPTO_KEY_REFERENCE;
17110Sstevel@tonic-gate obj_wrapkey.wk_wrapping_key.ck_obj_id = wrappingkey_p->k_handle;
17120Sstevel@tonic-gate obj_wrapkey.wk_object_handle = key_p->k_handle;
17130Sstevel@tonic-gate obj_wrapkey.wk_wrapped_key_len = *pulWrappedKeyLen;
17140Sstevel@tonic-gate obj_wrapkey.wk_wrapped_key = (char *)pWrappedKey;
17150Sstevel@tonic-gate
17160Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_WRAP_KEY, &obj_wrapkey)) < 0) {
17170Sstevel@tonic-gate if (errno != EINTR)
17180Sstevel@tonic-gate break;
17190Sstevel@tonic-gate }
17200Sstevel@tonic-gate if (r < 0) {
17210Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
17220Sstevel@tonic-gate } else {
17230Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_wrapkey.wk_return_value);
17240Sstevel@tonic-gate }
17250Sstevel@tonic-gate
17260Sstevel@tonic-gate /*
17270Sstevel@tonic-gate * Besides rv == CKR_OK, we will set the value of pulWrappedKeyLen
17280Sstevel@tonic-gate * when the applciation-supplied wrapped key buffer is too small.
17290Sstevel@tonic-gate * The situation that the application only asks for the length of
17300Sstevel@tonic-gate * the wrapped key is covered in rv == CKR_OK.
17310Sstevel@tonic-gate */
17320Sstevel@tonic-gate if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) {
17330Sstevel@tonic-gate *pulWrappedKeyLen = obj_wrapkey.wk_wrapped_key_len;
17340Sstevel@tonic-gate }
17350Sstevel@tonic-gate
1736214Smcpowers OBJ_REFRELE(key_p);
1737214Smcpowers OBJ_REFRELE(wrappingkey_p);
17380Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
17390Sstevel@tonic-gate return (rv);
17400Sstevel@tonic-gate }
17410Sstevel@tonic-gate
17420Sstevel@tonic-gate
17430Sstevel@tonic-gate CK_RV
C_UnwrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hUnwrappingKey,CK_BYTE_PTR pWrappedKey,CK_ULONG ulWrappedKeyLen,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)17440Sstevel@tonic-gate C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
17450Sstevel@tonic-gate CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey,
17460Sstevel@tonic-gate CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
17470Sstevel@tonic-gate CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
17480Sstevel@tonic-gate {
17490Sstevel@tonic-gate CK_RV rv = CKR_OK;
17500Sstevel@tonic-gate kernel_session_t *session_p;
17510Sstevel@tonic-gate kernel_object_t *unwrappingkey_p;
17520Sstevel@tonic-gate kernel_object_t *new_objp = NULL;
17530Sstevel@tonic-gate kernel_slot_t *pslot;
17540Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE;
17550Sstevel@tonic-gate CK_BBOOL is_pri_obj;
17560Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE;
17570Sstevel@tonic-gate CK_MECHANISM_INFO info;
17580Sstevel@tonic-gate uint32_t k_mi_flags;
17590Sstevel@tonic-gate CK_BYTE *clear_key_val = NULL;
17600Sstevel@tonic-gate CK_ULONG ulDataLen;
17610Sstevel@tonic-gate CK_ATTRIBUTE_PTR newTemplate = NULL;
17620Sstevel@tonic-gate crypto_mech_type_t k_mech_type;
17630Sstevel@tonic-gate crypto_object_unwrap_key_t obj_unwrapkey;
17640Sstevel@tonic-gate int r;
17650Sstevel@tonic-gate
17660Sstevel@tonic-gate if (!kernel_initialized)
17670Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
17680Sstevel@tonic-gate
17690Sstevel@tonic-gate if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL) {
17700Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
17710Sstevel@tonic-gate }
17720Sstevel@tonic-gate
17730Sstevel@tonic-gate if ((pTemplate == NULL) && (ulAttributeCount != 0)) {
17740Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
17750Sstevel@tonic-gate }
17760Sstevel@tonic-gate
17770Sstevel@tonic-gate /* Obtain the session pointer. */
17780Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
17790Sstevel@tonic-gate if (rv != CKR_OK)
17800Sstevel@tonic-gate return (rv);
17810Sstevel@tonic-gate
17820Sstevel@tonic-gate /* Obtain the wrapping key object pointer. */
17830Sstevel@tonic-gate HANDLE2OBJECT(hUnwrappingKey, unwrappingkey_p, rv);
17840Sstevel@tonic-gate if (rv != CKR_OK) {
1785214Smcpowers REFRELE(session_p, ses_lock_held);
1786214Smcpowers return (rv);
17870Sstevel@tonic-gate }
17880Sstevel@tonic-gate
17890Sstevel@tonic-gate /*
17900Sstevel@tonic-gate * If the HW provider doesn't support C_UnwrapKey, we will try
17910Sstevel@tonic-gate * to emulate it in the library.
17920Sstevel@tonic-gate */
17930Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid];
17944219Smcpowers if ((!pslot->sl_func_list.fl_object_create) &&
17954219Smcpowers (!pslot->sl_func_list.fl_key_unwrap)) {
17960Sstevel@tonic-gate rv = get_mechanism_info(pslot, pMechanism->mechanism, &info,
17970Sstevel@tonic-gate &k_mi_flags);
17980Sstevel@tonic-gate if (rv != CKR_OK) {
17990Sstevel@tonic-gate goto failed_exit;
18000Sstevel@tonic-gate }
18010Sstevel@tonic-gate
18020Sstevel@tonic-gate /*
18030Sstevel@tonic-gate * If the mechanism flag doesn't have CKF_UNWRAP, and it's
18040Sstevel@tonic-gate * an unwrapping of a secret key object, then help this
18050Sstevel@tonic-gate * out with a decryption followed by an object creation.
18060Sstevel@tonic-gate */
18070Sstevel@tonic-gate if (!(k_mi_flags & CRYPTO_FG_UNWRAP) &&
18080Sstevel@tonic-gate (k_mi_flags & CRYPTO_FG_DECRYPT) &&
18090Sstevel@tonic-gate (is_secret_key_template(pTemplate, ulAttributeCount))) {
18100Sstevel@tonic-gate
18110Sstevel@tonic-gate /* First allocate space for the recovered key value */
18120Sstevel@tonic-gate clear_key_val = malloc(ulWrappedKeyLen);
18130Sstevel@tonic-gate if (clear_key_val == NULL) {
18140Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
18150Sstevel@tonic-gate goto failed_exit;
18160Sstevel@tonic-gate }
18170Sstevel@tonic-gate
18180Sstevel@tonic-gate rv = kernel_decrypt_init(session_p, unwrappingkey_p,
18190Sstevel@tonic-gate pMechanism);
18200Sstevel@tonic-gate if (rv != CKR_OK) {
18210Sstevel@tonic-gate goto failed_exit;
18220Sstevel@tonic-gate }
18230Sstevel@tonic-gate
18240Sstevel@tonic-gate ulDataLen = ulWrappedKeyLen;
18250Sstevel@tonic-gate rv = kernel_decrypt(session_p, pWrappedKey,
18260Sstevel@tonic-gate ulWrappedKeyLen, clear_key_val, &ulDataLen);
18270Sstevel@tonic-gate if (rv != CKR_OK) {
18280Sstevel@tonic-gate goto failed_exit;
18290Sstevel@tonic-gate }
18300Sstevel@tonic-gate
18314219Smcpowers newTemplate = grow_template(pTemplate, ulAttributeCount,
18324219Smcpowers ulAttributeCount + 1);
18330Sstevel@tonic-gate if (newTemplate == NULL) {
18340Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
18350Sstevel@tonic-gate goto failed_exit;
18360Sstevel@tonic-gate }
18374219Smcpowers /* Now add the CKA_VALUE attribute to template */
18380Sstevel@tonic-gate newTemplate[ulAttributeCount].type = CKA_VALUE;
18390Sstevel@tonic-gate newTemplate[ulAttributeCount].pValue = clear_key_val;
18400Sstevel@tonic-gate newTemplate[ulAttributeCount].ulValueLen = ulDataLen;
18410Sstevel@tonic-gate
18420Sstevel@tonic-gate /* Finally create the key, based on the new template */
18430Sstevel@tonic-gate rv = kernel_add_object(newTemplate,
18440Sstevel@tonic-gate ulAttributeCount + 1, phKey, session_p);
18450Sstevel@tonic-gate (void) free(clear_key_val);
18460Sstevel@tonic-gate (void) free(newTemplate);
1847214Smcpowers OBJ_REFRELE(unwrappingkey_p);
18480Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
18490Sstevel@tonic-gate return (rv);
18500Sstevel@tonic-gate } else {
18510Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
18520Sstevel@tonic-gate goto failed_exit;
18530Sstevel@tonic-gate }
18540Sstevel@tonic-gate }
18550Sstevel@tonic-gate
18560Sstevel@tonic-gate /*
18570Sstevel@tonic-gate * If we come here, the HW provider must have registered the unwrapkey
18580Sstevel@tonic-gate * entry. Therefore, the unwrap key will be performed in the HW
18590Sstevel@tonic-gate * provider.
18600Sstevel@tonic-gate */
18610Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
18620Sstevel@tonic-gate if (rv != CKR_OK) {
18630Sstevel@tonic-gate goto failed_exit;
18640Sstevel@tonic-gate }
18650Sstevel@tonic-gate
18660Sstevel@tonic-gate /* Create an object wrapper for the new key in the library first */
18670Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t));
18680Sstevel@tonic-gate if (new_objp == NULL) {
18690Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
18700Sstevel@tonic-gate goto failed_exit;
18710Sstevel@tonic-gate }
18720Sstevel@tonic-gate
18730Sstevel@tonic-gate /* Process the attributes */
18740Sstevel@tonic-gate rv = process_object_attributes(pTemplate, ulAttributeCount,
18750Sstevel@tonic-gate &obj_unwrapkey.uk_attributes, &is_token_obj);
18760Sstevel@tonic-gate if (rv != CKR_OK) {
18770Sstevel@tonic-gate goto failed_exit;
18780Sstevel@tonic-gate }
18790Sstevel@tonic-gate
18800Sstevel@tonic-gate /* Cannot create a token object with a READ-ONLY session. */
18810Sstevel@tonic-gate if (is_token_obj && session_p->ses_RO) {
18820Sstevel@tonic-gate free_object_attributes(obj_unwrapkey.uk_attributes,
18830Sstevel@tonic-gate ulAttributeCount);
18840Sstevel@tonic-gate rv = CKR_SESSION_READ_ONLY;
18850Sstevel@tonic-gate goto failed_exit;
18860Sstevel@tonic-gate }
18870Sstevel@tonic-gate
18880Sstevel@tonic-gate /* Make the CRYPTO_UNWRAP_KEY ioctl call. */
18890Sstevel@tonic-gate obj_unwrapkey.uk_session = session_p->k_session;
18900Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_type = k_mech_type;
18910Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_param = pMechanism->pParameter;
18920Sstevel@tonic-gate obj_unwrapkey.uk_mechanism.cm_param_len = pMechanism->ulParameterLen;
18930Sstevel@tonic-gate obj_unwrapkey.uk_unwrapping_key.ck_format = CRYPTO_KEY_REFERENCE;
18940Sstevel@tonic-gate obj_unwrapkey.uk_unwrapping_key.ck_obj_id = unwrappingkey_p->k_handle;
18950Sstevel@tonic-gate obj_unwrapkey.uk_wrapped_key = (char *)pWrappedKey;
18960Sstevel@tonic-gate obj_unwrapkey.uk_wrapped_key_len = ulWrappedKeyLen;
18970Sstevel@tonic-gate obj_unwrapkey.uk_count = ulAttributeCount;
18980Sstevel@tonic-gate
18990Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_UNWRAP_KEY, &obj_unwrapkey)) < 0) {
19000Sstevel@tonic-gate if (errno != EINTR)
19010Sstevel@tonic-gate break;
19020Sstevel@tonic-gate }
19030Sstevel@tonic-gate if (r < 0) {
19040Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
19050Sstevel@tonic-gate } else {
19060Sstevel@tonic-gate rv = crypto2pkcs11_error_number(obj_unwrapkey.uk_return_value);
19070Sstevel@tonic-gate }
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate free_object_attributes(obj_unwrapkey.uk_attributes, ulAttributeCount);
19100Sstevel@tonic-gate if (rv != CKR_OK) {
19110Sstevel@tonic-gate goto failed_exit;
19120Sstevel@tonic-gate }
19130Sstevel@tonic-gate
19140Sstevel@tonic-gate /* Get the CKA_PRIVATE value for the unwrapped key. */
19150Sstevel@tonic-gate rv = get_cka_private_value(session_p, obj_unwrapkey.uk_object_handle,
19160Sstevel@tonic-gate &is_pri_obj);
19170Sstevel@tonic-gate if (rv != CKR_OK) {
19180Sstevel@tonic-gate goto failed_exit;
19190Sstevel@tonic-gate }
19200Sstevel@tonic-gate
19210Sstevel@tonic-gate /*
19220Sstevel@tonic-gate * Store the kernel object handle in the new key object wrapper and
19230Sstevel@tonic-gate * initialize it.
19240Sstevel@tonic-gate */
19250Sstevel@tonic-gate new_objp->k_handle = obj_unwrapkey.uk_object_handle;
19260Sstevel@tonic-gate new_objp->is_lib_obj = B_FALSE;
19270Sstevel@tonic-gate new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
19280Sstevel@tonic-gate new_objp->extra_attrlistp = NULL;
19290Sstevel@tonic-gate
19300Sstevel@tonic-gate if (is_pri_obj)
19310Sstevel@tonic-gate new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
19320Sstevel@tonic-gate else
19330Sstevel@tonic-gate new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
19340Sstevel@tonic-gate
19350Sstevel@tonic-gate if (is_token_obj)
19360Sstevel@tonic-gate new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
19370Sstevel@tonic-gate else
19380Sstevel@tonic-gate new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
19390Sstevel@tonic-gate
19400Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
19410Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
19420Sstevel@tonic-gate
19430Sstevel@tonic-gate /*
19440Sstevel@tonic-gate * Add the new object to the slot's token object list if it is a
19450Sstevel@tonic-gate * a token object. Otherwise, add it to the session's object list.
19460Sstevel@tonic-gate */
19470Sstevel@tonic-gate if (is_token_obj) {
19480Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid];
19490Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot);
19500Sstevel@tonic-gate } else {
19510Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p);
19520Sstevel@tonic-gate }
19530Sstevel@tonic-gate
19540Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp;
1955214Smcpowers OBJ_REFRELE(unwrappingkey_p);
19560Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
19570Sstevel@tonic-gate return (rv);
19580Sstevel@tonic-gate
19590Sstevel@tonic-gate failed_exit:
1960214Smcpowers OBJ_REFRELE(unwrappingkey_p);
19610Sstevel@tonic-gate if (new_objp != NULL)
19620Sstevel@tonic-gate (void) free(new_objp);
19630Sstevel@tonic-gate
19640Sstevel@tonic-gate if (clear_key_val != NULL)
19650Sstevel@tonic-gate (void) free(clear_key_val);
19660Sstevel@tonic-gate
19670Sstevel@tonic-gate if (newTemplate != NULL)
19680Sstevel@tonic-gate (void) free(newTemplate);
19690Sstevel@tonic-gate
19700Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
19710Sstevel@tonic-gate return (rv);
19720Sstevel@tonic-gate }
19730Sstevel@tonic-gate
19744219Smcpowers /*
19754219Smcpowers * Get sufficient attributes from a base key to pass by value in a
19764219Smcpowers * crypto_key structure. Storage for attributes is allocated.
19774219Smcpowers * For EC public keys, it is CKA_EC_PARAMS and CKA_EC_POINT.
19784219Smcpowers * For EC private keys, it is CKA_EC_PARAMS and CKA_VALUE.
19794219Smcpowers */
19804219Smcpowers static int
get_base_key_attributes(kernel_object_t * base_key,crypto_key_t * key_by_value)19814219Smcpowers get_base_key_attributes(kernel_object_t *base_key, crypto_key_t *key_by_value)
19824219Smcpowers {
19834219Smcpowers CK_ATTRIBUTE tmp;
1984*10669SMark.Powers@Sun.COM crypto_object_attribute_t *attrs = NULL;
19854219Smcpowers biginteger_t *big;
1986*10669SMark.Powers@Sun.COM int i, count = 0, rv;
19874219Smcpowers
19884219Smcpowers switch (base_key->key_type) {
19894219Smcpowers case CKK_EC:
1990*10669SMark.Powers@Sun.COM count = 2;
1991*10669SMark.Powers@Sun.COM attrs = malloc(count * sizeof (crypto_object_attribute_t));
19924219Smcpowers if (attrs == NULL) {
19934219Smcpowers rv = CKR_HOST_MEMORY;
19944219Smcpowers goto out;
19954219Smcpowers }
1996*10669SMark.Powers@Sun.COM bzero(attrs, count * sizeof (crypto_object_attribute_t));
19974219Smcpowers
19984219Smcpowers (void) pthread_mutex_lock(&base_key->object_mutex);
19994219Smcpowers
20004219Smcpowers if (!base_key->is_lib_obj) {
20014219Smcpowers rv = CRYPTO_ARGUMENTS_BAD;
20024219Smcpowers goto out;
20034219Smcpowers }
20044219Smcpowers
20054219Smcpowers if (base_key->class != CKO_PUBLIC_KEY &&
20064219Smcpowers base_key->class != CKO_PRIVATE_KEY) {
20074219Smcpowers rv = CRYPTO_ARGUMENTS_BAD;
20084219Smcpowers goto out;
20094219Smcpowers }
20104219Smcpowers
20114219Smcpowers /*
20124219Smcpowers * Both public and private EC keys should have
20134219Smcpowers * a CKA_EC_PARAMS attribute.
20144219Smcpowers */
20154219Smcpowers tmp.type = CKA_EC_PARAMS;
20164219Smcpowers tmp.pValue = NULL;
20174219Smcpowers
20184219Smcpowers /* get size of attribute */
20194219Smcpowers rv = kernel_get_attribute(base_key, &tmp);
20204219Smcpowers if (rv != CKR_OK) {
20214219Smcpowers goto out;
20224219Smcpowers }
20234219Smcpowers
20244219Smcpowers tmp.pValue = malloc(tmp.ulValueLen);
20254219Smcpowers if (tmp.pValue == NULL) {
20264219Smcpowers rv = CKR_HOST_MEMORY;
20274219Smcpowers goto out;
20284219Smcpowers }
20294219Smcpowers rv = kernel_get_attribute(base_key, &tmp);
20304219Smcpowers if (rv != CKR_OK) {
2031*10669SMark.Powers@Sun.COM free(tmp.pValue);
20324219Smcpowers goto out;
20334219Smcpowers }
20344219Smcpowers attrs[0].oa_type = tmp.type;
20354219Smcpowers attrs[0].oa_value = tmp.pValue;
20364219Smcpowers attrs[0].oa_value_len = tmp.ulValueLen;
20374219Smcpowers
20384219Smcpowers switch (base_key->class) {
20394219Smcpowers case CKO_PUBLIC_KEY:
20404219Smcpowers big = OBJ_PUB_EC_POINT(base_key);
20414219Smcpowers tmp.type = CKA_EC_POINT;
20424219Smcpowers break;
20434219Smcpowers
20444219Smcpowers case CKO_PRIVATE_KEY:
20454219Smcpowers big = OBJ_PRI_EC_VALUE(base_key);
20464219Smcpowers tmp.type = CKA_VALUE;
20474219Smcpowers break;
20484219Smcpowers
20494219Smcpowers default:
20504219Smcpowers rv = CKR_ATTRIBUTE_TYPE_INVALID;
20514219Smcpowers goto out;
20524219Smcpowers }
20534219Smcpowers tmp.ulValueLen = big->big_value_len;
20544219Smcpowers tmp.pValue = malloc(tmp.ulValueLen);
20554219Smcpowers if (tmp.pValue == NULL) {
20564219Smcpowers rv = CKR_HOST_MEMORY;
20574219Smcpowers goto out;
20584219Smcpowers }
20594219Smcpowers rv = kernel_get_attribute(base_key, &tmp);
20604219Smcpowers if (rv != CKR_OK) {
2061*10669SMark.Powers@Sun.COM free(tmp.pValue);
20624219Smcpowers goto out;
20634219Smcpowers }
20644219Smcpowers attrs[1].oa_type = tmp.type;
20654219Smcpowers attrs[1].oa_value = tmp.pValue;
20664219Smcpowers attrs[1].oa_value_len = tmp.ulValueLen;
20674219Smcpowers key_by_value->ck_attrs = attrs;
20684219Smcpowers key_by_value->ck_count = 2;
20694219Smcpowers break;
20704219Smcpowers
20714219Smcpowers case CKK_DH:
2072*10669SMark.Powers@Sun.COM count = 3;
2073*10669SMark.Powers@Sun.COM attrs = malloc(count * sizeof (crypto_object_attribute_t));
20744219Smcpowers if (attrs == NULL) {
20754219Smcpowers rv = CKR_HOST_MEMORY;
20764219Smcpowers goto out;
20774219Smcpowers }
2078*10669SMark.Powers@Sun.COM bzero(attrs, count * sizeof (crypto_object_attribute_t));
20794219Smcpowers
20804219Smcpowers (void) pthread_mutex_lock(&base_key->object_mutex);
20814219Smcpowers
20824219Smcpowers if (!base_key->is_lib_obj) {
20834219Smcpowers rv = CRYPTO_ARGUMENTS_BAD;
20844219Smcpowers goto out;
20854219Smcpowers }
20864219Smcpowers
20874219Smcpowers if (base_key->class != CKO_PRIVATE_KEY) {
20884219Smcpowers rv = CRYPTO_ARGUMENTS_BAD;
20894219Smcpowers goto out;
20904219Smcpowers }
20914219Smcpowers tmp.type = CKA_BASE;
20924219Smcpowers tmp.pValue = NULL;
20934219Smcpowers
20944219Smcpowers /* get size of attribute */
20954219Smcpowers rv = kernel_get_attribute(base_key, &tmp);
20964219Smcpowers if (rv != CKR_OK) {
20974219Smcpowers goto out;
20984219Smcpowers }
20994219Smcpowers
21004219Smcpowers tmp.pValue = malloc(tmp.ulValueLen);
21014219Smcpowers if (tmp.pValue == NULL) {
21024219Smcpowers rv = CKR_HOST_MEMORY;
21034219Smcpowers goto out;
21044219Smcpowers }
21054219Smcpowers rv = kernel_get_attribute(base_key, &tmp);
21064219Smcpowers if (rv != CKR_OK) {
2107*10669SMark.Powers@Sun.COM free(tmp.pValue);
21084219Smcpowers goto out;
21094219Smcpowers }
21104219Smcpowers attrs[0].oa_type = tmp.type;
21114219Smcpowers attrs[0].oa_value = tmp.pValue;
21124219Smcpowers attrs[0].oa_value_len = tmp.ulValueLen;
21134219Smcpowers
21144219Smcpowers tmp.type = CKA_PRIME;
21154219Smcpowers tmp.pValue = NULL;
21164219Smcpowers
21174219Smcpowers /* get size of attribute */
21184219Smcpowers rv = kernel_get_attribute(base_key, &tmp);
21194219Smcpowers if (rv != CKR_OK) {
21204219Smcpowers goto out;
21214219Smcpowers }
21224219Smcpowers
21234219Smcpowers tmp.pValue = malloc(tmp.ulValueLen);
21244219Smcpowers if (tmp.pValue == NULL) {
21254219Smcpowers rv = CKR_HOST_MEMORY;
21264219Smcpowers goto out;
21274219Smcpowers }
21284219Smcpowers rv = kernel_get_attribute(base_key, &tmp);
21294219Smcpowers if (rv != CKR_OK) {
2130*10669SMark.Powers@Sun.COM free(tmp.pValue);
21314219Smcpowers goto out;
21324219Smcpowers }
21334219Smcpowers attrs[1].oa_type = tmp.type;
21344219Smcpowers attrs[1].oa_value = tmp.pValue;
21354219Smcpowers attrs[1].oa_value_len = tmp.ulValueLen;
21364219Smcpowers
2137*10669SMark.Powers@Sun.COM big = OBJ_PRI_DH_VALUE(base_key);
21384219Smcpowers tmp.type = CKA_VALUE;
21394219Smcpowers
21404219Smcpowers tmp.ulValueLen = big->big_value_len;
21414219Smcpowers tmp.pValue = malloc(tmp.ulValueLen);
21424219Smcpowers if (tmp.pValue == NULL) {
21434219Smcpowers rv = CKR_HOST_MEMORY;
21444219Smcpowers goto out;
21454219Smcpowers }
21464219Smcpowers rv = kernel_get_attribute(base_key, &tmp);
21474219Smcpowers if (rv != CKR_OK) {
2148*10669SMark.Powers@Sun.COM free(tmp.pValue);
21494219Smcpowers goto out;
21504219Smcpowers }
21514219Smcpowers attrs[2].oa_type = tmp.type;
21524219Smcpowers attrs[2].oa_value = tmp.pValue;
21534219Smcpowers attrs[2].oa_value_len = tmp.ulValueLen;
21544219Smcpowers key_by_value->ck_attrs = attrs;
21554219Smcpowers key_by_value->ck_count = 3;
21564219Smcpowers break;
21574219Smcpowers
21584219Smcpowers default:
21594219Smcpowers rv = CKR_ATTRIBUTE_TYPE_INVALID;
21604219Smcpowers goto out;
21614219Smcpowers }
21624219Smcpowers (void) pthread_mutex_unlock(&base_key->object_mutex);
21634219Smcpowers return (CKR_OK);
21644219Smcpowers
21654219Smcpowers out:
21664219Smcpowers (void) pthread_mutex_unlock(&base_key->object_mutex);
2167*10669SMark.Powers@Sun.COM if (attrs != NULL) {
2168*10669SMark.Powers@Sun.COM for (i = 0; i < count; i++) {
2169*10669SMark.Powers@Sun.COM if (attrs[i].oa_value != NULL)
2170*10669SMark.Powers@Sun.COM free(attrs[i].oa_value);
2171*10669SMark.Powers@Sun.COM }
2172*10669SMark.Powers@Sun.COM free(attrs);
2173*10669SMark.Powers@Sun.COM }
21744219Smcpowers return (rv);
21754219Smcpowers }
21764219Smcpowers
21774219Smcpowers CK_RV
derive_key_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * basekey_p,kernel_object_t * new_objp)21784219Smcpowers derive_key_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate,
21794219Smcpowers CK_ULONG ulAttributeCount, kernel_session_t *session_p,
21804219Smcpowers crypto_mech_type_t k_mech_type, kernel_object_t *basekey_p,
21814219Smcpowers kernel_object_t *new_objp)
21824219Smcpowers {
21834219Smcpowers crypto_nostore_derive_key_t obj_ndk;
21844219Smcpowers char *key_buf = NULL;
21854219Smcpowers CK_ATTRIBUTE_PTR newTemplate = NULL;
21864219Smcpowers CK_BBOOL is_token_obj = FALSE;
21874219Smcpowers CK_RV rv = CKR_OK;
21884219Smcpowers CK_ULONG secret_class = CKO_SECRET_KEY;
21894219Smcpowers ulong_t key_len = 0;
21904219Smcpowers uint_t attr_count = 0;
21914219Smcpowers boolean_t removed;
21924219Smcpowers boolean_t has_class;
21934219Smcpowers int r, n;
21944219Smcpowers
21954219Smcpowers obj_ndk.ndk_in_count = 0;
21964219Smcpowers obj_ndk.ndk_out_count = 0;
21974219Smcpowers obj_ndk.ndk_base_key.ck_count = 0;
21984219Smcpowers
21994219Smcpowers rv = get_key_len_from_template(pMechanism, pTemplate, ulAttributeCount,
22004219Smcpowers basekey_p, &key_len);
22014219Smcpowers if (rv != CKR_OK) {
22024219Smcpowers goto failed_exit;
22034219Smcpowers }
22044219Smcpowers
22054219Smcpowers if ((key_buf = malloc(key_len)) == NULL) {
22064219Smcpowers rv = CKR_HOST_MEMORY;
22074219Smcpowers goto failed_exit;
22084219Smcpowers }
22094219Smcpowers
22104219Smcpowers has_class = attribute_in_template(CKA_CLASS, pTemplate,
22114219Smcpowers ulAttributeCount);
22124219Smcpowers
22134219Smcpowers attr_count = ulAttributeCount + 1;
22144219Smcpowers if (!has_class)
22154219Smcpowers attr_count++;
22164219Smcpowers
22174219Smcpowers newTemplate = grow_template(pTemplate, ulAttributeCount, attr_count);
22184219Smcpowers if (newTemplate == NULL) {
22194219Smcpowers rv = CKR_HOST_MEMORY;
22204219Smcpowers goto failed_exit;
22214219Smcpowers }
22224219Smcpowers
22234219Smcpowers n = ulAttributeCount;
22244219Smcpowers if (!has_class) {
22254219Smcpowers newTemplate[n].type = CKA_CLASS;
22264219Smcpowers newTemplate[n].pValue = (caddr_t)&secret_class;
22274219Smcpowers newTemplate[n].ulValueLen = sizeof (secret_class);
22284219Smcpowers n++;
22294219Smcpowers }
22304219Smcpowers
22314219Smcpowers /* Add CKA_VALUE to the template */
22324219Smcpowers newTemplate[n].type = CKA_VALUE;
22334219Smcpowers newTemplate[n].pValue = (caddr_t)key_buf;
22344219Smcpowers newTemplate[n].ulValueLen = key_len;
22354219Smcpowers
22364219Smcpowers rv = process_object_attributes(newTemplate, attr_count - 1,
22374219Smcpowers &obj_ndk.ndk_in_attributes, &is_token_obj);
22384219Smcpowers if (rv != CKR_OK) {
22394219Smcpowers goto failed_exit;
22404219Smcpowers }
2241*10669SMark.Powers@Sun.COM obj_ndk.ndk_in_count = attr_count - 1;
22424219Smcpowers
22434219Smcpowers rv = process_object_attributes(&newTemplate[attr_count - 1],
22444219Smcpowers 1, &obj_ndk.ndk_out_attributes, &is_token_obj);
22454219Smcpowers if (rv != CKR_OK) {
22464219Smcpowers goto failed_exit;
22474219Smcpowers }
2248*10669SMark.Powers@Sun.COM obj_ndk.ndk_out_count = 1;
22494219Smcpowers
22504219Smcpowers /* Cannot create a token object with a READ-ONLY session. */
22514219Smcpowers if (is_token_obj && session_p->ses_RO) {
22524219Smcpowers rv = CKR_SESSION_READ_ONLY;
22534219Smcpowers goto failed_exit;
22544219Smcpowers }
22554219Smcpowers
22564219Smcpowers obj_ndk.ndk_session = session_p->k_session;
22574219Smcpowers obj_ndk.ndk_mechanism.cm_type = k_mech_type;
22584219Smcpowers obj_ndk.ndk_mechanism.cm_param = pMechanism->pParameter;
22594219Smcpowers obj_ndk.ndk_mechanism.cm_param_len = pMechanism->ulParameterLen;
22604219Smcpowers
22614219Smcpowers /*
22624219Smcpowers * Obtain the attributes of base key and pass them by value.
22634219Smcpowers */
22644219Smcpowers rv = get_base_key_attributes(basekey_p, &obj_ndk.ndk_base_key);
22654219Smcpowers if (rv != CKR_OK) {
22664219Smcpowers goto failed_exit;
22674219Smcpowers }
22684219Smcpowers
22694219Smcpowers obj_ndk.ndk_base_key.ck_format = CRYPTO_KEY_ATTR_LIST;
22704219Smcpowers
22714219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_DERIVE_KEY,
22724219Smcpowers &obj_ndk)) < 0) {
22734219Smcpowers if (errno != EINTR)
22744219Smcpowers break;
22754219Smcpowers }
22764219Smcpowers if (r < 0) {
22774219Smcpowers rv = CKR_FUNCTION_FAILED;
22784219Smcpowers } else {
22794219Smcpowers rv = crypto2pkcs11_error_number(obj_ndk.ndk_return_value);
22804219Smcpowers }
22814219Smcpowers free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count);
22824219Smcpowers free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs,
22834219Smcpowers &obj_ndk.ndk_base_key.ck_count);
22844219Smcpowers if (rv != CKR_OK) {
22854219Smcpowers goto failed_exit;
22864219Smcpowers }
22874219Smcpowers
22884219Smcpowers rv = get_object_attributes(&newTemplate[attr_count - 1],
22894219Smcpowers 1, obj_ndk.ndk_out_attributes);
22904219Smcpowers free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count);
22914219Smcpowers if (rv != CRYPTO_SUCCESS) {
22924219Smcpowers goto failed_exit;
22934219Smcpowers }
22944219Smcpowers
22954219Smcpowers removed = remove_one_attribute(newTemplate, CKA_VALUE_LEN,
22964219Smcpowers attr_count, B_FALSE);
22974219Smcpowers
22984219Smcpowers rv = kernel_build_object(newTemplate, removed ? attr_count - 1 :
22994219Smcpowers attr_count, new_objp, session_p, KERNEL_GEN_KEY);
23004219Smcpowers if (rv != CRYPTO_SUCCESS) {
23014219Smcpowers goto failed_exit;
23024219Smcpowers }
23034219Smcpowers
23044219Smcpowers free(key_buf);
23054219Smcpowers free(newTemplate);
23064219Smcpowers new_objp->is_lib_obj = B_TRUE;
23074219Smcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
23084219Smcpowers return (CKR_OK);
23094219Smcpowers
23104219Smcpowers failed_exit:
23114219Smcpowers if (key_buf != NULL)
23124219Smcpowers free(key_buf);
23134219Smcpowers if (newTemplate != NULL)
23144219Smcpowers free(newTemplate);
23154219Smcpowers free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count);
23164219Smcpowers free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count);
23174219Smcpowers free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs,
23184219Smcpowers &obj_ndk.ndk_base_key.ck_count);
23194219Smcpowers return (rv);
23204219Smcpowers }
23210Sstevel@tonic-gate
23220Sstevel@tonic-gate CK_RV
C_DeriveKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hBaseKey,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)23230Sstevel@tonic-gate C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
23240Sstevel@tonic-gate CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
23250Sstevel@tonic-gate CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
23260Sstevel@tonic-gate {
23270Sstevel@tonic-gate CK_RV rv = CKR_OK;
23280Sstevel@tonic-gate kernel_session_t *session_p;
23290Sstevel@tonic-gate kernel_object_t *basekey_p;
23300Sstevel@tonic-gate kernel_object_t *new_objp;
23310Sstevel@tonic-gate kernel_slot_t *pslot;
23320Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE;
23330Sstevel@tonic-gate CK_BBOOL is_pri_obj;
23340Sstevel@tonic-gate CK_BBOOL is_token_obj = FALSE;
23350Sstevel@tonic-gate crypto_mech_type_t k_mech_type;
23360Sstevel@tonic-gate int r;
23370Sstevel@tonic-gate
23380Sstevel@tonic-gate if (!kernel_initialized)
23390Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
23400Sstevel@tonic-gate
23410Sstevel@tonic-gate /* Obtain the session pointer. */
23420Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
23430Sstevel@tonic-gate if (rv != CKR_OK)
23440Sstevel@tonic-gate return (rv);
23450Sstevel@tonic-gate
2346872Sizick if (pMechanism == NULL) {
2347214Smcpowers REFRELE(session_p, ses_lock_held);
2348214Smcpowers return (CKR_ARGUMENTS_BAD);
23490Sstevel@tonic-gate }
23500Sstevel@tonic-gate
23510Sstevel@tonic-gate if ((pTemplate == NULL && ulAttributeCount != 0) ||
23520Sstevel@tonic-gate (pTemplate != NULL && ulAttributeCount == 0)) {
2353214Smcpowers REFRELE(session_p, ses_lock_held);
2354214Smcpowers return (CKR_ARGUMENTS_BAD);
23550Sstevel@tonic-gate }
23560Sstevel@tonic-gate
23570Sstevel@tonic-gate /* Obtain the base key object pointer. */
23580Sstevel@tonic-gate HANDLE2OBJECT(hBaseKey, basekey_p, rv);
23590Sstevel@tonic-gate if (rv != CKR_OK) {
2360214Smcpowers REFRELE(session_p, ses_lock_held);
2361214Smcpowers return (rv);
23620Sstevel@tonic-gate }
23630Sstevel@tonic-gate
23640Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */
23650Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
23660Sstevel@tonic-gate if (rv != CKR_OK) {
23670Sstevel@tonic-gate goto failed_exit;
23680Sstevel@tonic-gate }
23690Sstevel@tonic-gate
23700Sstevel@tonic-gate /* Create an object wrapper in the library for the generated key. */
23710Sstevel@tonic-gate new_objp = calloc(1, sizeof (kernel_object_t));
23720Sstevel@tonic-gate if (new_objp == NULL) {
23730Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
23740Sstevel@tonic-gate goto failed_exit;
23750Sstevel@tonic-gate }
23760Sstevel@tonic-gate
23774219Smcpowers /*
23784219Smcpowers * Special Case: if token does not support object creation,
23794219Smcpowers * but does support key derivation by value, then create a session
23804219Smcpowers * object and initialize with values returned by token.
23814219Smcpowers */
23824219Smcpowers pslot = slot_table[session_p->ses_slotid];
23834219Smcpowers if (!pslot->sl_func_list.fl_object_create) {
23844219Smcpowers rv = derive_key_by_value(pMechanism, pTemplate,
23854219Smcpowers ulAttributeCount, session_p, k_mech_type, basekey_p,
23864219Smcpowers new_objp);
23874219Smcpowers if (rv != CKR_OK)
23884219Smcpowers goto failed_exit;
23894219Smcpowers } else {
23904219Smcpowers crypto_derive_key_t obj_dk;
23910Sstevel@tonic-gate
23924219Smcpowers rv = process_object_attributes(pTemplate, ulAttributeCount,
23934219Smcpowers &obj_dk.dk_attributes, &is_token_obj);
23944219Smcpowers if (rv != CKR_OK) {
23954219Smcpowers goto failed_exit;
23964219Smcpowers }
23974219Smcpowers
23984219Smcpowers /* Cannot create a token object with a READ-ONLY session. */
23994219Smcpowers if (is_token_obj && session_p->ses_RO) {
24004219Smcpowers free_object_attributes(obj_dk.dk_attributes,
24014219Smcpowers ulAttributeCount);
24024219Smcpowers rv = CKR_SESSION_READ_ONLY;
24034219Smcpowers goto failed_exit;
24044219Smcpowers }
24054219Smcpowers
24064219Smcpowers obj_dk.dk_session = session_p->k_session;
24074219Smcpowers obj_dk.dk_mechanism.cm_type = k_mech_type;
24084219Smcpowers obj_dk.dk_mechanism.cm_param = pMechanism->pParameter;
24094219Smcpowers obj_dk.dk_mechanism.cm_param_len = pMechanism->ulParameterLen;
24104219Smcpowers obj_dk.dk_base_key.ck_format = CRYPTO_KEY_REFERENCE;
24114219Smcpowers obj_dk.dk_base_key.ck_obj_id = basekey_p->k_handle;
24124219Smcpowers obj_dk.dk_count = ulAttributeCount;
24130Sstevel@tonic-gate
24144219Smcpowers while ((r = ioctl(kernel_fd, CRYPTO_DERIVE_KEY, &obj_dk)) < 0) {
24154219Smcpowers if (errno != EINTR)
24164219Smcpowers break;
24174219Smcpowers }
24184219Smcpowers if (r < 0) {
24194219Smcpowers rv = CKR_FUNCTION_FAILED;
24204219Smcpowers } else {
24214219Smcpowers rv = crypto2pkcs11_error_number(obj_dk.dk_return_value);
24224219Smcpowers }
24234219Smcpowers
24244219Smcpowers free_object_attributes(obj_dk.dk_attributes, ulAttributeCount);
24254219Smcpowers if (rv != CKR_OK) {
24264219Smcpowers goto failed_exit;
24274219Smcpowers }
24280Sstevel@tonic-gate
24294219Smcpowers /* Get the CKA_PRIVATE value for the derived key. */
24304219Smcpowers rv = get_cka_private_value(session_p, obj_dk.dk_object_handle,
24314219Smcpowers &is_pri_obj);
24324219Smcpowers if (rv != CKR_OK) {
24334219Smcpowers goto failed_exit;
24344219Smcpowers }
24354219Smcpowers
24364219Smcpowers /*
24374219Smcpowers * Store the kernel object handle into the new derived key
24384219Smcpowers * object and finish the object initialization.
24394219Smcpowers */
24404219Smcpowers new_objp->is_lib_obj = B_FALSE;
24414219Smcpowers new_objp->k_handle = obj_dk.dk_object_handle;
24424219Smcpowers new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
24434219Smcpowers new_objp->extra_attrlistp = NULL;
24444219Smcpowers
24454219Smcpowers if (is_pri_obj)
24464219Smcpowers new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
24474219Smcpowers else
24484219Smcpowers new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
24494219Smcpowers
24504219Smcpowers if (is_token_obj)
24514219Smcpowers new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
24524219Smcpowers else
24534219Smcpowers new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
24540Sstevel@tonic-gate }
24550Sstevel@tonic-gate (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
24560Sstevel@tonic-gate new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
24570Sstevel@tonic-gate
24580Sstevel@tonic-gate /*
24590Sstevel@tonic-gate * Add the new derived object to the slot's token list if it is a
24600Sstevel@tonic-gate * token object. Otherwise, add it to the session's object list.
24610Sstevel@tonic-gate */
24620Sstevel@tonic-gate if (is_token_obj) {
24630Sstevel@tonic-gate pslot = slot_table[session_p->ses_slotid];
24640Sstevel@tonic-gate kernel_add_token_object_to_slot(new_objp, pslot);
24650Sstevel@tonic-gate } else {
24660Sstevel@tonic-gate kernel_add_object_to_session(new_objp, session_p);
24670Sstevel@tonic-gate }
24680Sstevel@tonic-gate
24690Sstevel@tonic-gate *phKey = (CK_OBJECT_HANDLE)new_objp;
2470214Smcpowers OBJ_REFRELE(basekey_p);
24710Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
24720Sstevel@tonic-gate return (rv);
24730Sstevel@tonic-gate
24740Sstevel@tonic-gate failed_exit:
2475214Smcpowers OBJ_REFRELE(basekey_p);
24760Sstevel@tonic-gate if (new_objp != NULL) {
24770Sstevel@tonic-gate (void) free(new_objp);
24780Sstevel@tonic-gate }
24790Sstevel@tonic-gate
24800Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
24810Sstevel@tonic-gate return (rv);
24820Sstevel@tonic-gate }
2483