17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5034448feSmcpowers * Common Development and Distribution License (the "License").
6034448feSmcpowers * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*5893fa69SDan OpenSolaris Anderson * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <stdlib.h>
277c478bd9Sstevel@tonic-gate #include <string.h>
287c478bd9Sstevel@tonic-gate #include <strings.h>
297c478bd9Sstevel@tonic-gate #include <errno.h>
307c478bd9Sstevel@tonic-gate #include <fcntl.h>
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/stat.h>
337c478bd9Sstevel@tonic-gate #include "metaGlobal.h"
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate /* Size of the template for creating key used for wrap/unwrap */
367c478bd9Sstevel@tonic-gate #define WRAP_KEY_TEMPLATE_SIZE 7
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate * Information necessary to create keys for C_WrapKey/C_UnwrapKey
407c478bd9Sstevel@tonic-gate */
417c478bd9Sstevel@tonic-gate typedef struct _wrap_info {
427c478bd9Sstevel@tonic-gate CK_OBJECT_CLASS class; /* class of the key for wrap/unwrap */
437c478bd9Sstevel@tonic-gate CK_KEY_TYPE key_type; /* key type of key for wrap/unwrap */
447c478bd9Sstevel@tonic-gate CK_ULONG key_length; /* length of key */
457c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE mech_type; /* mech used for wrap/unwrap */
467c478bd9Sstevel@tonic-gate CK_ULONG iv_length; /* length of iv for mech */
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate boolean_t src_supports;
497c478bd9Sstevel@tonic-gate boolean_t dst_supports;
507c478bd9Sstevel@tonic-gate } wrap_info_t;
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate extern pthread_rwlock_t meta_sessionlist_lock;
537c478bd9Sstevel@tonic-gate extern meta_session_t *meta_sessionlist_head;
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate static wrap_info_t common_wrap_info[] = {
567c478bd9Sstevel@tonic-gate {CKO_SECRET_KEY, CKK_AES, 16, CKM_AES_CBC_PAD, 16, B_FALSE, B_FALSE},
577c478bd9Sstevel@tonic-gate {CKO_SECRET_KEY, CKK_DES3, 24, CKM_DES3_CBC_PAD, 8, B_FALSE, B_FALSE},
587c478bd9Sstevel@tonic-gate {CKO_SECRET_KEY, CKK_DES, 8, CKM_DES_CBC_PAD, 8, B_FALSE, B_FALSE},
597c478bd9Sstevel@tonic-gate };
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate static unsigned int num_common_wrap_info =
627c478bd9Sstevel@tonic-gate sizeof (common_wrap_info) / sizeof (wrap_info_t);
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate static wrap_info_t special_wrap_info[] = {
657c478bd9Sstevel@tonic-gate {CKO_SECRET_KEY, CKK_SKIPJACK, 12, CKM_SKIPJACK_WRAP, 0,
667c478bd9Sstevel@tonic-gate B_FALSE, B_FALSE},
677c478bd9Sstevel@tonic-gate {CKO_SECRET_KEY, CKK_BATON, 40, CKM_BATON_WRAP, 0,
687c478bd9Sstevel@tonic-gate B_FALSE, B_FALSE},
697c478bd9Sstevel@tonic-gate {CKO_SECRET_KEY, CKK_JUNIPER, 40, CKM_JUNIPER_WRAP, 0,
707c478bd9Sstevel@tonic-gate B_FALSE, B_FALSE},
717c478bd9Sstevel@tonic-gate };
727c478bd9Sstevel@tonic-gate static unsigned int num_special_wrap_info =
737c478bd9Sstevel@tonic-gate sizeof (special_wrap_info) / sizeof (wrap_info_t);
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate static wrap_info_t rsa_wrap_info[] = {
767c478bd9Sstevel@tonic-gate {CKO_PUBLIC_KEY, CKK_RSA, 0, CKM_RSA_PKCS, 0,
777c478bd9Sstevel@tonic-gate B_FALSE, B_FALSE},
787c478bd9Sstevel@tonic-gate {CKO_PUBLIC_KEY, CKK_RSA, 0, CKM_RSA_X_509, 0,
797c478bd9Sstevel@tonic-gate B_FALSE, B_FALSE},
807c478bd9Sstevel@tonic-gate };
817c478bd9Sstevel@tonic-gate static unsigned int num_rsa_wrap_info =
827c478bd9Sstevel@tonic-gate sizeof (rsa_wrap_info) / sizeof (wrap_info_t);
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate static pthread_rwlock_t meta_objectclose_lock;
867c478bd9Sstevel@tonic-gate static pthread_rwlock_t tokenobject_list_lock;
877c478bd9Sstevel@tonic-gate static meta_object_t *tokenobject_list_head;
887c478bd9Sstevel@tonic-gate
89034448feSmcpowers CK_BBOOL falsevalue = FALSE;
90034448feSmcpowers CK_BBOOL truevalue = TRUE;
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate * Public and private exponent, and Module value for
947c478bd9Sstevel@tonic-gate * creating the RSA public/private key.
957c478bd9Sstevel@tonic-gate *
967c478bd9Sstevel@tonic-gate */
977c478bd9Sstevel@tonic-gate static CK_BYTE PubExpo[3] = {0x01, 0x00, 0x01};
987c478bd9Sstevel@tonic-gate CK_BYTE PriExpo[128] = {
997c478bd9Sstevel@tonic-gate 0x8e, 0xc9, 0x70, 0x57, 0x6b, 0xcd, 0xfb, 0xa9,
1007c478bd9Sstevel@tonic-gate 0x19, 0xad, 0xcd, 0x91, 0x69, 0xd5, 0x52, 0xec,
1017c478bd9Sstevel@tonic-gate 0x72, 0x1e, 0x45, 0x15, 0x06, 0xdc, 0x65, 0x2d,
1027c478bd9Sstevel@tonic-gate 0x98, 0xc4, 0xce, 0x33, 0x54, 0x15, 0x70, 0x8d,
1037c478bd9Sstevel@tonic-gate 0xfa, 0x65, 0xea, 0x53, 0x44, 0xf3, 0x3e, 0x3f,
1047c478bd9Sstevel@tonic-gate 0xb4, 0x4c, 0x60, 0xd5, 0x01, 0x2d, 0xa4, 0x12,
1057c478bd9Sstevel@tonic-gate 0x99, 0xbf, 0x3f, 0x0b, 0xcd, 0xbb, 0x24, 0x10,
1067c478bd9Sstevel@tonic-gate 0x60, 0x30, 0x5e, 0x58, 0xf8, 0x59, 0xaa, 0xd1,
1077c478bd9Sstevel@tonic-gate 0x63, 0x3b, 0xbc, 0xcb, 0x94, 0x58, 0x38, 0x24,
1087c478bd9Sstevel@tonic-gate 0xfc, 0x65, 0x25, 0xc5, 0xa6, 0x51, 0xa2, 0x2e,
1097c478bd9Sstevel@tonic-gate 0xf1, 0x5e, 0xf5, 0xc1, 0xf5, 0x46, 0xf7, 0xbd,
1107c478bd9Sstevel@tonic-gate 0xc7, 0x62, 0xa8, 0xe2, 0x27, 0xd6, 0x94, 0x5b,
1117c478bd9Sstevel@tonic-gate 0xd3, 0xa2, 0xb5, 0x76, 0x42, 0x67, 0x6b, 0x86,
1127c478bd9Sstevel@tonic-gate 0x91, 0x97, 0x4d, 0x07, 0x92, 0x00, 0x4a, 0xdf,
1137c478bd9Sstevel@tonic-gate 0x0b, 0x65, 0x64, 0x05, 0x03, 0x48, 0x27, 0xeb,
1147c478bd9Sstevel@tonic-gate 0xce, 0x9a, 0x49, 0x7f, 0x3e, 0x10, 0xe0, 0x01};
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate static CK_BYTE Modulus[128] = {
1177c478bd9Sstevel@tonic-gate 0x94, 0x32, 0xb9, 0x12, 0x1d, 0x68, 0x2c, 0xda,
1187c478bd9Sstevel@tonic-gate 0x2b, 0xe0, 0xe4, 0x97, 0x1b, 0x4d, 0xdc, 0x43,
1197c478bd9Sstevel@tonic-gate 0xdf, 0x38, 0x6e, 0x7b, 0x9f, 0x07, 0x58, 0xae,
1207c478bd9Sstevel@tonic-gate 0x9d, 0x82, 0x1e, 0xc7, 0xbc, 0x92, 0xbf, 0xd3,
1217c478bd9Sstevel@tonic-gate 0xce, 0x00, 0xbb, 0x91, 0xc9, 0x79, 0x06, 0x03,
1227c478bd9Sstevel@tonic-gate 0x1f, 0xbc, 0x9f, 0x94, 0x75, 0x29, 0x5f, 0xd7,
1237c478bd9Sstevel@tonic-gate 0xc5, 0xf3, 0x73, 0x8a, 0xa4, 0x35, 0x43, 0x7a,
1247c478bd9Sstevel@tonic-gate 0x00, 0x32, 0x97, 0x3e, 0x86, 0xef, 0x70, 0x6f,
1257c478bd9Sstevel@tonic-gate 0x18, 0x56, 0x15, 0xaa, 0x6a, 0x87, 0xe7, 0x8d,
1267c478bd9Sstevel@tonic-gate 0x7d, 0xdd, 0x1f, 0xa4, 0xe4, 0x31, 0xd4, 0x7a,
1277c478bd9Sstevel@tonic-gate 0x8c, 0x0e, 0x20, 0xd2, 0x23, 0xf5, 0x57, 0x3c,
1287c478bd9Sstevel@tonic-gate 0x1b, 0xa8, 0x44, 0xa4, 0x57, 0x8f, 0x33, 0x52,
1297c478bd9Sstevel@tonic-gate 0xad, 0x83, 0xae, 0x4a, 0x97, 0xa6, 0x1e, 0xa6,
1307c478bd9Sstevel@tonic-gate 0x2b, 0xfa, 0xea, 0xeb, 0x6e, 0x71, 0xb8, 0xb6,
1317c478bd9Sstevel@tonic-gate 0x0a, 0x36, 0xed, 0x83, 0xce, 0xb0, 0xdf, 0xc1,
1327c478bd9Sstevel@tonic-gate 0xd4, 0x3a, 0xe9, 0x99, 0x6f, 0xf3, 0x96, 0xb7};
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate static CK_RV
1357c478bd9Sstevel@tonic-gate meta_clone_template_setup(meta_object_t *object,
1367c478bd9Sstevel@tonic-gate const generic_attr_t *attributes, size_t num_attributes);
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate * meta_objectManager_initialize
1407c478bd9Sstevel@tonic-gate *
1417c478bd9Sstevel@tonic-gate * Called from meta_Initialize. Initializes all the variables used
1427c478bd9Sstevel@tonic-gate * by the object manager.
1437c478bd9Sstevel@tonic-gate */
1447c478bd9Sstevel@tonic-gate CK_RV
meta_objectManager_initialize()1457c478bd9Sstevel@tonic-gate meta_objectManager_initialize()
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate if (pthread_rwlock_init(&meta_objectclose_lock, NULL) != 0) {
1487c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate if (pthread_rwlock_init(&tokenobject_list_lock, NULL) != 0) {
1527c478bd9Sstevel@tonic-gate (void) pthread_rwlock_destroy(&meta_objectclose_lock);
1537c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate tokenobject_list_head = NULL;
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate return (CKR_OK);
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate void
meta_objectManager_finalize()1627c478bd9Sstevel@tonic-gate meta_objectManager_finalize()
1637c478bd9Sstevel@tonic-gate {
1647c478bd9Sstevel@tonic-gate /*
1657c478bd9Sstevel@tonic-gate * If there are still any token object in the list, need to
1667c478bd9Sstevel@tonic-gate * deactivate all of them.
1677c478bd9Sstevel@tonic-gate */
1687c478bd9Sstevel@tonic-gate (void) meta_token_object_deactivate(ALL_TOKEN);
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate (void) pthread_rwlock_destroy(&meta_objectclose_lock);
1717c478bd9Sstevel@tonic-gate (void) pthread_rwlock_destroy(&tokenobject_list_lock);
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate /*
1777c478bd9Sstevel@tonic-gate * meta_handle2object
1787c478bd9Sstevel@tonic-gate *
1797c478bd9Sstevel@tonic-gate * Convert a CK_OBJECT_HANDLE to the corresponding metaobject. If
1807c478bd9Sstevel@tonic-gate * successful, a reader-lock on the object will be held to indicate
1817c478bd9Sstevel@tonic-gate * that it's in use. Call OBJRELEASE() when finished.
1827c478bd9Sstevel@tonic-gate *
1837c478bd9Sstevel@tonic-gate */
1847c478bd9Sstevel@tonic-gate CK_RV
meta_handle2object(CK_OBJECT_HANDLE hObject,meta_object_t ** object)1857c478bd9Sstevel@tonic-gate meta_handle2object(CK_OBJECT_HANDLE hObject, meta_object_t **object)
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate meta_object_t *tmp_object = (meta_object_t *)(hObject);
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate /* Check for bad args (eg CK_INVALID_HANDLE, which is 0/NULL). */
1907c478bd9Sstevel@tonic-gate if (tmp_object == NULL) {
1917c478bd9Sstevel@tonic-gate *object = NULL;
1927c478bd9Sstevel@tonic-gate return (CKR_OBJECT_HANDLE_INVALID);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate /* Lock to ensure the magic-check + read-lock is atomic. */
1977c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&meta_objectclose_lock);
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate if (tmp_object->magic_marker != METASLOT_OBJECT_MAGIC) {
2007c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&meta_objectclose_lock);
2017c478bd9Sstevel@tonic-gate *object = NULL;
2027c478bd9Sstevel@tonic-gate return (CKR_OBJECT_HANDLE_INVALID);
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&tmp_object->object_lock);
2057c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&meta_objectclose_lock);
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate *object = tmp_object;
2087c478bd9Sstevel@tonic-gate return (CKR_OK);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate /*
2137c478bd9Sstevel@tonic-gate * meta_object_alloc
2147c478bd9Sstevel@tonic-gate *
2157c478bd9Sstevel@tonic-gate * Creates a new metaobject, but does not yet add it to the object list.
2167c478bd9Sstevel@tonic-gate * Once the caller has finished initializing the object (by setting
2177c478bd9Sstevel@tonic-gate * object attributes), meta_object_add should be called. This two-step
2187c478bd9Sstevel@tonic-gate * process prevents others from seeing the object until fully intitialized.
2197c478bd9Sstevel@tonic-gate *
2207c478bd9Sstevel@tonic-gate */
2217c478bd9Sstevel@tonic-gate CK_RV
meta_object_alloc(meta_session_t * session,meta_object_t ** object)2227c478bd9Sstevel@tonic-gate meta_object_alloc(meta_session_t *session, meta_object_t **object)
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate meta_object_t *new_object;
2257c478bd9Sstevel@tonic-gate CK_ULONG num_slots;
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate /* Allocate memory for the object. */
2287c478bd9Sstevel@tonic-gate new_object = calloc(1, sizeof (meta_object_t));
2297c478bd9Sstevel@tonic-gate if (new_object == NULL)
2307c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate num_slots = meta_slotManager_get_slotcount();
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate new_object->clones = calloc(num_slots, sizeof (slot_object_t *));
2357c478bd9Sstevel@tonic-gate if (new_object->clones == NULL) {
2367c478bd9Sstevel@tonic-gate free(new_object);
2377c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate new_object->tried_create_clone = calloc(num_slots, sizeof (boolean_t));
2417c478bd9Sstevel@tonic-gate if (new_object->tried_create_clone == NULL) {
2427c478bd9Sstevel@tonic-gate free(new_object->clones);
2437c478bd9Sstevel@tonic-gate free(new_object);
2447c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate /* Initialize the object fields. */
2487c478bd9Sstevel@tonic-gate new_object->magic_marker = METASLOT_OBJECT_MAGIC;
2497c478bd9Sstevel@tonic-gate (void) pthread_rwlock_init(&new_object->object_lock, NULL);
2507c478bd9Sstevel@tonic-gate (void) pthread_rwlock_init(&new_object->attribute_lock, NULL);
2517c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_object->clone_create_lock, NULL);
2527c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&new_object->isClosingObject_lock, NULL);
2537c478bd9Sstevel@tonic-gate new_object->creator_session = session;
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate *object = new_object;
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate return (CKR_OK);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate
2617c478bd9Sstevel@tonic-gate /*
2627c478bd9Sstevel@tonic-gate * meta_object_get_attr
2637c478bd9Sstevel@tonic-gate *
2647c478bd9Sstevel@tonic-gate * Get attribute values to fill in attribute values
2657c478bd9Sstevel@tonic-gate * being kept in the metaslot object. The following 4 attributes
2667c478bd9Sstevel@tonic-gate * in the meta_object_t structure will be filled in:
2677c478bd9Sstevel@tonic-gate * isToken, isPrivate, isSensitive, isExtractable
2687c478bd9Sstevel@tonic-gate *
2697c478bd9Sstevel@tonic-gate * It's basically an easy way to do a C_GetAttributeValue.
2707c478bd9Sstevel@tonic-gate * So, the hSession argument is assumed
2717c478bd9Sstevel@tonic-gate * to be valid, and the pointer to meta_object_t is also assumed
2727c478bd9Sstevel@tonic-gate * to be valid.
2737c478bd9Sstevel@tonic-gate */
2747c478bd9Sstevel@tonic-gate CK_RV
meta_object_get_attr(slot_session_t * slot_session,CK_OBJECT_HANDLE hObject,meta_object_t * object)2757c478bd9Sstevel@tonic-gate meta_object_get_attr(slot_session_t *slot_session, CK_OBJECT_HANDLE hObject,
2767c478bd9Sstevel@tonic-gate meta_object_t *object)
2777c478bd9Sstevel@tonic-gate {
278034448feSmcpowers CK_BBOOL is_sensitive = object->isSensitive;
279034448feSmcpowers CK_BBOOL is_extractable = object->isExtractable;
280034448feSmcpowers CK_BBOOL is_token = B_FALSE, is_private = B_FALSE;
281034448feSmcpowers CK_KEY_TYPE keytype;
2827c478bd9Sstevel@tonic-gate CK_OBJECT_CLASS class;
2837c478bd9Sstevel@tonic-gate CK_ATTRIBUTE attrs[3];
2847c478bd9Sstevel@tonic-gate CK_RV rv;
2857c478bd9Sstevel@tonic-gate CK_SESSION_HANDLE hSession = slot_session->hSession;
2867c478bd9Sstevel@tonic-gate CK_SLOT_ID fw_st_id = slot_session->fw_st_id;
287034448feSmcpowers int count = 1;
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate attrs[0].type = CKA_CLASS;
2907c478bd9Sstevel@tonic-gate attrs[0].pValue = &class;
2917c478bd9Sstevel@tonic-gate attrs[0].ulValueLen = sizeof (class);
2927c478bd9Sstevel@tonic-gate
293034448feSmcpowers if (object->isFreeObject != FREE_ENABLED) {
2947c478bd9Sstevel@tonic-gate attrs[1].type = CKA_TOKEN;
2957c478bd9Sstevel@tonic-gate attrs[1].pValue = &is_token;
2967c478bd9Sstevel@tonic-gate attrs[1].ulValueLen = sizeof (is_token);
297034448feSmcpowers count++;
298034448feSmcpowers }
2997c478bd9Sstevel@tonic-gate
300034448feSmcpowers /*
301034448feSmcpowers * If this is a freeobject, we already know the Private value
302034448feSmcpowers * and we don't want to overwrite it with the wrong value
303034448feSmcpowers */
304034448feSmcpowers if (object->isFreeObject <= FREE_DISABLED) {
305034448feSmcpowers attrs[count].type = CKA_PRIVATE;
306034448feSmcpowers attrs[count].pValue = &is_private;
307034448feSmcpowers attrs[count].ulValueLen = sizeof (is_private);
308034448feSmcpowers count++;
309034448feSmcpowers } else
310034448feSmcpowers is_private = object->isPrivate;
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, hObject,
313034448feSmcpowers attrs, count);
3147c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
3157c478bd9Sstevel@tonic-gate return (rv);
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate
318034448feSmcpowers count = 0;
319034448feSmcpowers switch (class) {
320034448feSmcpowers case CKO_PRIVATE_KEY:
321034448feSmcpowers case CKO_SECRET_KEY:
322034448feSmcpowers /* Only need to check these for private & secret keys */
323034448feSmcpowers attrs[0].type = CKA_EXTRACTABLE;
324034448feSmcpowers attrs[0].pValue = &is_extractable;
325034448feSmcpowers attrs[0].ulValueLen = sizeof (is_extractable);
326034448feSmcpowers count = 1;
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate /*
329034448feSmcpowers * If this is a freeobject, we already know the Sensitive
330034448feSmcpowers * value and we don't want to overwrite it with the wrong
331034448feSmcpowers * value.
3327c478bd9Sstevel@tonic-gate */
3337c478bd9Sstevel@tonic-gate
334034448feSmcpowers if (object->isFreeObject <= FREE_DISABLED) {
335034448feSmcpowers attrs[1].type = CKA_SENSITIVE;
336034448feSmcpowers attrs[1].pValue = &is_sensitive;
337034448feSmcpowers attrs[1].ulValueLen = sizeof (is_sensitive);
338034448feSmcpowers count = 2;
3397c478bd9Sstevel@tonic-gate
340034448feSmcpowers /*
341034448feSmcpowers * We only need the key type if this is the first
342034448feSmcpowers * time we've looked at the object
343034448feSmcpowers */
344034448feSmcpowers if (object->isFreeObject == FREE_UNCHECKED) {
345034448feSmcpowers attrs[2].type = CKA_KEY_TYPE;
346034448feSmcpowers attrs[2].pValue = &keytype;
347034448feSmcpowers attrs[2].ulValueLen = sizeof (keytype);
348034448feSmcpowers count = 3;
3497c478bd9Sstevel@tonic-gate }
350034448feSmcpowers }
351034448feSmcpowers
352034448feSmcpowers break;
353034448feSmcpowers
354034448feSmcpowers case CKO_PUBLIC_KEY:
355034448feSmcpowers if (object->isFreeObject == FREE_UNCHECKED) {
356034448feSmcpowers attrs[count].type = CKA_KEY_TYPE;
357034448feSmcpowers attrs[count].pValue = &keytype;
358034448feSmcpowers attrs[count].ulValueLen = sizeof (keytype);
359034448feSmcpowers count++;
360034448feSmcpowers }
3617c478bd9Sstevel@tonic-gate is_sensitive = CK_FALSE;
3627c478bd9Sstevel@tonic-gate is_extractable = CK_TRUE;
363034448feSmcpowers break;
364034448feSmcpowers
365034448feSmcpowers default:
366034448feSmcpowers object->isFreeObject = FREE_DISABLED;
367034448feSmcpowers is_sensitive = CK_FALSE;
368034448feSmcpowers is_extractable = CK_TRUE;
369034448feSmcpowers };
370034448feSmcpowers
371034448feSmcpowers if (count > 0) {
372034448feSmcpowers rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, hObject,
373034448feSmcpowers attrs, count);
374034448feSmcpowers if (rv != CKR_OK) {
375034448feSmcpowers return (rv);
376034448feSmcpowers }
377034448feSmcpowers
378034448feSmcpowers if (object->isFreeObject == FREE_UNCHECKED) {
379034448feSmcpowers if (keytype == CKK_EC || keytype == CKK_RSA ||
380034448feSmcpowers keytype == CKK_DH) {
381034448feSmcpowers if (metaslot_config.auto_key_migrate) {
382034448feSmcpowers object->isFreeObject = FREE_DISABLED;
383034448feSmcpowers object->isFreeToken = FREE_DISABLED;
384034448feSmcpowers }
385034448feSmcpowers
386034448feSmcpowers object->isFreeObject = FREE_ENABLED;
387034448feSmcpowers if (is_token)
388034448feSmcpowers object->isFreeToken = FREE_ENABLED;
389034448feSmcpowers } else
390034448feSmcpowers object->isFreeObject = FREE_DISABLED;
391034448feSmcpowers
392034448feSmcpowers }
393034448feSmcpowers
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate object->isToken = is_token;
3977c478bd9Sstevel@tonic-gate object->isPrivate = is_private;
3987c478bd9Sstevel@tonic-gate object->isSensitive = is_sensitive;
3997c478bd9Sstevel@tonic-gate object->isExtractable = is_extractable;
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate return (CKR_OK);
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate /*
4067c478bd9Sstevel@tonic-gate * meta_object_activate
4077c478bd9Sstevel@tonic-gate *
4087c478bd9Sstevel@tonic-gate * Add a new metaobject to the list of objects. See also meta_object_create,
4097c478bd9Sstevel@tonic-gate * which would be called to create an object before it is added.
4107c478bd9Sstevel@tonic-gate */
4117c478bd9Sstevel@tonic-gate void
meta_object_activate(meta_object_t * new_object)4127c478bd9Sstevel@tonic-gate meta_object_activate(meta_object_t *new_object)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate pthread_rwlock_t *list_lock;
4157c478bd9Sstevel@tonic-gate meta_object_t **list_head;
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate /*
4187c478bd9Sstevel@tonic-gate * For session objects, we keep the list in the session that created
4197c478bd9Sstevel@tonic-gate * this object, because this object will be destroyed when that session
4207c478bd9Sstevel@tonic-gate * is closed.
4217c478bd9Sstevel@tonic-gate *
4227c478bd9Sstevel@tonic-gate * For token objects, the list is global (ie, not associated with any
4237c478bd9Sstevel@tonic-gate * particular session).
4247c478bd9Sstevel@tonic-gate */
4257c478bd9Sstevel@tonic-gate if (new_object->isToken) {
4267c478bd9Sstevel@tonic-gate list_lock = &tokenobject_list_lock;
4277c478bd9Sstevel@tonic-gate list_head = &tokenobject_list_head;
4287c478bd9Sstevel@tonic-gate } else {
4297c478bd9Sstevel@tonic-gate list_lock = &new_object->creator_session->object_list_lock;
4307c478bd9Sstevel@tonic-gate list_head = &new_object->creator_session->object_list_head;
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate /* Add object to the list of objects. */
4347c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(list_lock);
4357c478bd9Sstevel@tonic-gate INSERT_INTO_LIST(*list_head, new_object);
4367c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(list_lock);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate /*
4417c478bd9Sstevel@tonic-gate * meta_object_deactivate
4427c478bd9Sstevel@tonic-gate *
4437c478bd9Sstevel@tonic-gate * Removes the object from the list of valid meta objects. Note
4447c478bd9Sstevel@tonic-gate * that this function does not clean up any allocated
4457c478bd9Sstevel@tonic-gate * resources (memory, object clones, etc). Cleaning up of
4468cae6764SAnthony Scarpino * allocated resources is done by calling the meta_object_dealloc()
4477c478bd9Sstevel@tonic-gate *
4487c478bd9Sstevel@tonic-gate */
4497c478bd9Sstevel@tonic-gate CK_RV
meta_object_deactivate(meta_object_t * object,boolean_t have_list_lock,boolean_t have_object_lock)4507c478bd9Sstevel@tonic-gate meta_object_deactivate(meta_object_t *object, boolean_t have_list_lock,
4517c478bd9Sstevel@tonic-gate boolean_t have_object_lock)
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate pthread_rwlock_t *list_lock;
4547c478bd9Sstevel@tonic-gate meta_object_t **list_head;
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate if (!have_object_lock) {
4577c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&object->object_lock);
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&object->isClosingObject_lock);
4617c478bd9Sstevel@tonic-gate if (object->isClosingObject) {
4627c478bd9Sstevel@tonic-gate /* Lost a delete race. */
4637c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object->isClosingObject_lock);
4647c478bd9Sstevel@tonic-gate OBJRELEASE(object);
4657c478bd9Sstevel@tonic-gate return (CKR_OBJECT_HANDLE_INVALID);
4667c478bd9Sstevel@tonic-gate }
4677c478bd9Sstevel@tonic-gate object->isClosingObject = B_TRUE;
4687c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object->isClosingObject_lock);
4697c478bd9Sstevel@tonic-gate
4708cae6764SAnthony Scarpino if (object->isToken || (object->isFreeToken == FREE_ENABLED)) {
4717c478bd9Sstevel@tonic-gate list_lock = &tokenobject_list_lock;
4727c478bd9Sstevel@tonic-gate list_head = &tokenobject_list_head;
4737c478bd9Sstevel@tonic-gate } else {
4747c478bd9Sstevel@tonic-gate list_lock = &object->creator_session->object_list_lock;
4757c478bd9Sstevel@tonic-gate list_head = &object->creator_session->object_list_head;
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate /*
4797c478bd9Sstevel@tonic-gate * Remove object from the object list. Once removed, it will not
4807c478bd9Sstevel@tonic-gate * be possible for another thread to begin using the object.
4817c478bd9Sstevel@tonic-gate */
4827c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&meta_objectclose_lock);
4837c478bd9Sstevel@tonic-gate if (!have_list_lock) {
4847c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(list_lock);
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate
4887c478bd9Sstevel@tonic-gate object->magic_marker = METASLOT_OBJECT_BADMAGIC;
4897c478bd9Sstevel@tonic-gate /*
4907c478bd9Sstevel@tonic-gate * Can't use the regular REMOVE_FROM_LIST() function because
4917c478bd9Sstevel@tonic-gate * that will miss the "error cleanup" situation where object is not yet
4927c478bd9Sstevel@tonic-gate * in the list (object->next == NULL && object->prev == NULL)
4937c478bd9Sstevel@tonic-gate */
4947c478bd9Sstevel@tonic-gate if (*list_head == object) {
4957c478bd9Sstevel@tonic-gate /* Object is the first one in the list */
4967c478bd9Sstevel@tonic-gate if (object->next) {
4977c478bd9Sstevel@tonic-gate *list_head = object->next;
4987c478bd9Sstevel@tonic-gate object->next->prev = NULL;
4997c478bd9Sstevel@tonic-gate } else {
5007c478bd9Sstevel@tonic-gate /* Object is the only one in the list */
5017c478bd9Sstevel@tonic-gate *list_head = NULL;
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate } else if (object->next != NULL || object->prev != NULL) {
5047c478bd9Sstevel@tonic-gate if (object->next) {
5057c478bd9Sstevel@tonic-gate object->prev->next = object->next;
5067c478bd9Sstevel@tonic-gate object->next->prev = object->prev;
5077c478bd9Sstevel@tonic-gate } else {
5087c478bd9Sstevel@tonic-gate /* Object is the last one in the list */
5097c478bd9Sstevel@tonic-gate object->prev->next = NULL;
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate }
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate if (!have_list_lock) {
5147c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(list_lock);
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&meta_objectclose_lock);
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate /*
5197c478bd9Sstevel@tonic-gate * Wait for anyone already using object to finish, by obtaining
5207c478bd9Sstevel@tonic-gate * a writer-lock (need to release our reader-lock first). Once we
5217c478bd9Sstevel@tonic-gate * get the write lock, we can just release it and finish cleaning
5227c478bd9Sstevel@tonic-gate * up the object.
5237c478bd9Sstevel@tonic-gate */
5247c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&object->object_lock); /* rdlock */
5257c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&object->object_lock);
5267c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&object->object_lock); /* wrlock */
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate return (CKR_OK);
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate /*
5347c478bd9Sstevel@tonic-gate * meta_object_dealloc
5357c478bd9Sstevel@tonic-gate *
5367c478bd9Sstevel@tonic-gate * Performs final object cleanup, releasing any allocated memory and
5377c478bd9Sstevel@tonic-gate * destroying any clones on other slots. Caller is assumed to have
5387c478bd9Sstevel@tonic-gate * called meta_object_deactivate() before this function.
5397c478bd9Sstevel@tonic-gate *
5407c478bd9Sstevel@tonic-gate * Caller is assumed to have only reference to object, but should have
5417c478bd9Sstevel@tonic-gate * released any lock.
5427c478bd9Sstevel@tonic-gate *
5437c478bd9Sstevel@tonic-gate * If "nukeSourceObj" argument is true, we will actually delete the
5447c478bd9Sstevel@tonic-gate * object from the underlying slot.
5457c478bd9Sstevel@tonic-gate */
5467c478bd9Sstevel@tonic-gate CK_RV
meta_object_dealloc(meta_session_t * session,meta_object_t * object,boolean_t nukeSourceObj)5478cae6764SAnthony Scarpino meta_object_dealloc(meta_session_t *session, meta_object_t *object,
5488cae6764SAnthony Scarpino boolean_t nukeSourceObj)
5497c478bd9Sstevel@tonic-gate {
5507c478bd9Sstevel@tonic-gate CK_RV rv, save_rv = CKR_OK;
5517c478bd9Sstevel@tonic-gate CK_ULONG slotnum, num_slots;
5527c478bd9Sstevel@tonic-gate CK_ULONG i;
5537c478bd9Sstevel@tonic-gate
5547c478bd9Sstevel@tonic-gate /* First, delete all the clones of this object on other slots. */
5557c478bd9Sstevel@tonic-gate num_slots = meta_slotManager_get_slotcount();
5567c478bd9Sstevel@tonic-gate for (slotnum = 0; slotnum < num_slots; slotnum++) {
5577c478bd9Sstevel@tonic-gate slot_session_t *obj_session;
5587c478bd9Sstevel@tonic-gate slot_object_t *clone;
5597c478bd9Sstevel@tonic-gate
5607c478bd9Sstevel@tonic-gate clone = object->clones[slotnum];
5617c478bd9Sstevel@tonic-gate if (clone == NULL)
5627c478bd9Sstevel@tonic-gate continue;
563034448feSmcpowers if (nukeSourceObj || (!object->isToken &&
564034448feSmcpowers !(object->isFreeToken == FREE_ENABLED &&
565034448feSmcpowers get_keystore_slotnum() == slotnum))) {
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate rv = meta_get_slot_session(slotnum, &obj_session,
5688cae6764SAnthony Scarpino (session == NULL) ?
5698cae6764SAnthony Scarpino object->creator_session->session_flags :
5708cae6764SAnthony Scarpino session->session_flags);
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
5737c478bd9Sstevel@tonic-gate rv = FUNCLIST(obj_session->fw_st_id)->\
5747c478bd9Sstevel@tonic-gate C_DestroyObject(obj_session->hSession,
5757c478bd9Sstevel@tonic-gate clone->hObject);
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate meta_release_slot_session(obj_session);
5787c478bd9Sstevel@tonic-gate if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
5797c478bd9Sstevel@tonic-gate save_rv = rv;
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate }
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate
5857c478bd9Sstevel@tonic-gate meta_slot_object_deactivate(clone);
5867c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(clone);
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate object->clones[slotnum] = NULL;
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate /* Now erase and delete any attributes in the metaobject. */
5927c478bd9Sstevel@tonic-gate dealloc_attributes(object->attributes, object->num_attributes);
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate free(object->clones);
5957c478bd9Sstevel@tonic-gate free(object->tried_create_clone);
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate if (object->clone_template) {
5987c478bd9Sstevel@tonic-gate for (i = 0; i < object->clone_template_size; i++) {
5997c478bd9Sstevel@tonic-gate free(((object->clone_template)[i]).pValue);
6007c478bd9Sstevel@tonic-gate }
6017c478bd9Sstevel@tonic-gate free(object->clone_template);
6027c478bd9Sstevel@tonic-gate }
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate /* Cleanup remaining object fields. */
6057c478bd9Sstevel@tonic-gate (void) pthread_rwlock_destroy(&object->object_lock);
6067c478bd9Sstevel@tonic-gate (void) pthread_rwlock_destroy(&object->attribute_lock);
6077c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&object->isClosingObject_lock);
6087c478bd9Sstevel@tonic-gate (void) pthread_mutex_destroy(&object->clone_create_lock);
6097c478bd9Sstevel@tonic-gate
6107c478bd9Sstevel@tonic-gate meta_object_delay_free(object);
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate return (save_rv);
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate /*
6177c478bd9Sstevel@tonic-gate * meta_slot_object_alloc
6187c478bd9Sstevel@tonic-gate */
6197c478bd9Sstevel@tonic-gate CK_RV
meta_slot_object_alloc(slot_object_t ** object)6207c478bd9Sstevel@tonic-gate meta_slot_object_alloc(slot_object_t **object) {
6217c478bd9Sstevel@tonic-gate slot_object_t *new_object;
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate new_object = calloc(1, sizeof (slot_object_t));
6247c478bd9Sstevel@tonic-gate if (new_object == NULL)
6257c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate *object = new_object;
6287c478bd9Sstevel@tonic-gate return (CKR_OK);
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate /*
6337c478bd9Sstevel@tonic-gate * meta_slot_object_activate
6347c478bd9Sstevel@tonic-gate */
6357c478bd9Sstevel@tonic-gate void
meta_slot_object_activate(slot_object_t * object,slot_session_t * creator_session,boolean_t isToken)6367c478bd9Sstevel@tonic-gate meta_slot_object_activate(slot_object_t *object,
6377c478bd9Sstevel@tonic-gate slot_session_t *creator_session, boolean_t isToken)
6387c478bd9Sstevel@tonic-gate {
6397c478bd9Sstevel@tonic-gate object->creator_session = creator_session;
6407c478bd9Sstevel@tonic-gate
6417c478bd9Sstevel@tonic-gate if (isToken) {
6427c478bd9Sstevel@tonic-gate extern slot_data_t *slots;
6437c478bd9Sstevel@tonic-gate slot_data_t *slot;
6447c478bd9Sstevel@tonic-gate
6457c478bd9Sstevel@tonic-gate slot = &(slots[object->creator_session->slotnum]);
6467c478bd9Sstevel@tonic-gate
6477c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&slot->tokenobject_list_lock);
6487c478bd9Sstevel@tonic-gate INSERT_INTO_LIST(slot->tokenobject_list_head, object);
6497c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&slot->tokenobject_list_lock);
6507c478bd9Sstevel@tonic-gate } else {
6517c478bd9Sstevel@tonic-gate slot_session_t *session = object->creator_session;
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate /* Add to session's list of session objects. */
6547c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&session->object_list_lock);
6557c478bd9Sstevel@tonic-gate INSERT_INTO_LIST(session->object_list_head, object);
6567c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&session->object_list_lock);
6577c478bd9Sstevel@tonic-gate }
658034448feSmcpowers
659034448feSmcpowers /*
660034448feSmcpowers * This set tells the slot object that we are in the token list,
661034448feSmcpowers * but does not cause harm with the metaobject knowing the object
662034448feSmcpowers * isn't a token, but a freetoken
663034448feSmcpowers */
664034448feSmcpowers
6657c478bd9Sstevel@tonic-gate object->isToken = isToken;
6667c478bd9Sstevel@tonic-gate }
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gate
6697c478bd9Sstevel@tonic-gate /*
6707c478bd9Sstevel@tonic-gate * meta_slot_object_deactivate
6717c478bd9Sstevel@tonic-gate *
6727c478bd9Sstevel@tonic-gate * Remove the specified slot object from the appropriate object list.
6737c478bd9Sstevel@tonic-gate */
6747c478bd9Sstevel@tonic-gate void
meta_slot_object_deactivate(slot_object_t * object)6757c478bd9Sstevel@tonic-gate meta_slot_object_deactivate(slot_object_t *object)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate slot_object_t **list_head;
6787c478bd9Sstevel@tonic-gate pthread_rwlock_t *list_lock;
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate if (object->isToken) {
6817c478bd9Sstevel@tonic-gate extern slot_data_t *slots;
6827c478bd9Sstevel@tonic-gate slot_data_t *slot;
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate slot = &(slots[object->creator_session->slotnum]);
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate list_head = &slot->tokenobject_list_head;
6877c478bd9Sstevel@tonic-gate list_lock = &slot->tokenobject_list_lock;
6887c478bd9Sstevel@tonic-gate } else {
6897c478bd9Sstevel@tonic-gate list_head = &object->creator_session->object_list_head;
6907c478bd9Sstevel@tonic-gate list_lock = &object->creator_session->object_list_lock;
6917c478bd9Sstevel@tonic-gate }
6927c478bd9Sstevel@tonic-gate
6937c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(list_lock);
6947c478bd9Sstevel@tonic-gate REMOVE_FROM_LIST(*list_head, object);
6957c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(list_lock);
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate /*
7007c478bd9Sstevel@tonic-gate * meta_slot_object_dealloc
7017c478bd9Sstevel@tonic-gate */
7027c478bd9Sstevel@tonic-gate void
meta_slot_object_dealloc(slot_object_t * object)7037c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(slot_object_t *object)
7047c478bd9Sstevel@tonic-gate {
7057c478bd9Sstevel@tonic-gate /* Not much cleanup for slot objects, unlike meta objects... */
7067c478bd9Sstevel@tonic-gate free(object);
7077c478bd9Sstevel@tonic-gate }
7087c478bd9Sstevel@tonic-gate
7097c478bd9Sstevel@tonic-gate
7107c478bd9Sstevel@tonic-gate /*
7117c478bd9Sstevel@tonic-gate * meta_object_copyin
7127c478bd9Sstevel@tonic-gate *
7137c478bd9Sstevel@tonic-gate * When a key is generated/derived/unwrapped, the attribute values
7147c478bd9Sstevel@tonic-gate * created by the token are not immediately read into our copy of the
7157c478bd9Sstevel@tonic-gate * attributes. We defer this work until we actually need to know.
7167c478bd9Sstevel@tonic-gate */
7177c478bd9Sstevel@tonic-gate CK_RV
meta_object_copyin(meta_object_t * object)7187c478bd9Sstevel@tonic-gate meta_object_copyin(meta_object_t *object)
7197c478bd9Sstevel@tonic-gate {
7207c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
7217c478bd9Sstevel@tonic-gate slot_session_t *session = NULL;
7227c478bd9Sstevel@tonic-gate CK_ATTRIBUTE *attrs = NULL, *attrs_with_val = NULL;
7237c478bd9Sstevel@tonic-gate slot_object_t *slot_object = NULL;
7247c478bd9Sstevel@tonic-gate CK_ULONG num_attrs = 0, i, num_attrs_with_val;
7257c478bd9Sstevel@tonic-gate CK_SESSION_HANDLE hSession;
7267c478bd9Sstevel@tonic-gate CK_SLOT_ID fw_st_id;
7277c478bd9Sstevel@tonic-gate
7287c478bd9Sstevel@tonic-gate /* Make sure no one else is looking at attributes. */
7297c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&object->attribute_lock);
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate /* Did we just lose a copyin race with another thread */
7327c478bd9Sstevel@tonic-gate if (object->attributes != NULL) {
7337c478bd9Sstevel@tonic-gate goto finish;
7347c478bd9Sstevel@tonic-gate }
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate slot_object = object->clones[object->master_clone_slotnum];
7377c478bd9Sstevel@tonic-gate
7387c478bd9Sstevel@tonic-gate rv = meta_get_slot_session(object->master_clone_slotnum, &session,
7397c478bd9Sstevel@tonic-gate object->creator_session->session_flags);
7407c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
7417c478bd9Sstevel@tonic-gate goto finish;
7427c478bd9Sstevel@tonic-gate }
7437c478bd9Sstevel@tonic-gate
7447c478bd9Sstevel@tonic-gate /*
7457c478bd9Sstevel@tonic-gate * first, get the master template of all the attributes
7467c478bd9Sstevel@tonic-gate * for this object
7477c478bd9Sstevel@tonic-gate */
7487c478bd9Sstevel@tonic-gate rv = get_master_attributes_by_object(session, slot_object,
7497c478bd9Sstevel@tonic-gate &(object->attributes), &(object->num_attributes));
7507c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
7517c478bd9Sstevel@tonic-gate goto finish;
7527c478bd9Sstevel@tonic-gate }
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate /*
7557c478bd9Sstevel@tonic-gate * Get value for each attribute items.
7567c478bd9Sstevel@tonic-gate *
7577c478bd9Sstevel@tonic-gate * Some attributes are required by the given object type.
7587c478bd9Sstevel@tonic-gate * Some are optional. Get all the values first, and then
7597c478bd9Sstevel@tonic-gate * make sure we have value for all required values,
7607c478bd9Sstevel@tonic-gate */
7617c478bd9Sstevel@tonic-gate attrs = calloc(object->num_attributes, sizeof (CK_ATTRIBUTE));
7627c478bd9Sstevel@tonic-gate if (attrs == NULL) {
7637c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
7647c478bd9Sstevel@tonic-gate goto finish;
7657c478bd9Sstevel@tonic-gate }
7667c478bd9Sstevel@tonic-gate
7677c478bd9Sstevel@tonic-gate
7687c478bd9Sstevel@tonic-gate for (i = 0; i < object->num_attributes; i++) {
7697c478bd9Sstevel@tonic-gate attrs[i].type =
7707c478bd9Sstevel@tonic-gate ((object->attributes[i]).attribute).type;
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate num_attrs = object->num_attributes;
7737c478bd9Sstevel@tonic-gate
7747c478bd9Sstevel@tonic-gate hSession = session->hSession;
7757c478bd9Sstevel@tonic-gate fw_st_id = session->fw_st_id;
7767c478bd9Sstevel@tonic-gate
7777c478bd9Sstevel@tonic-gate /* first, call C_GetAttributeValue() to get size for each attribute */
7787c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
7797c478bd9Sstevel@tonic-gate slot_object->hObject, attrs, num_attrs);
7807c478bd9Sstevel@tonic-gate /*
7817c478bd9Sstevel@tonic-gate * If the return value is not CKR_OK, allow it to be
7827c478bd9Sstevel@tonic-gate * CKR_ATTRIBUTE_TYPE_INVALID for now.
7837c478bd9Sstevel@tonic-gate * Some attributes defined in PKCS#11 version 2.11
7847c478bd9Sstevel@tonic-gate * might not be defined in earlier versions. We will
7857c478bd9Sstevel@tonic-gate * TRY to work with those providers if the attribute
7867c478bd9Sstevel@tonic-gate * is optional.
7877c478bd9Sstevel@tonic-gate */
7887c478bd9Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_ATTRIBUTE_TYPE_INVALID)) {
7897c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; /* make sure rv is appropriate */
7907c478bd9Sstevel@tonic-gate goto finish;
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate
7937c478bd9Sstevel@tonic-gate /*
7947c478bd9Sstevel@tonic-gate * allocate space.
7957c478bd9Sstevel@tonic-gate * Since we don't know how many attributes have
7967c478bd9Sstevel@tonic-gate * values at this time, just assume all of them
7977c478bd9Sstevel@tonic-gate * have values so we save one loop to count the number
7987c478bd9Sstevel@tonic-gate * of attributes that have value.
7997c478bd9Sstevel@tonic-gate */
8007c478bd9Sstevel@tonic-gate attrs_with_val = calloc(num_attrs, sizeof (CK_ATTRIBUTE));
8017c478bd9Sstevel@tonic-gate if (attrs_with_val == NULL) {
8027c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
8037c478bd9Sstevel@tonic-gate goto finish;
8047c478bd9Sstevel@tonic-gate }
8057c478bd9Sstevel@tonic-gate
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate num_attrs_with_val = 0;
8087c478bd9Sstevel@tonic-gate for (i = 0; i < num_attrs; i++) {
8097c478bd9Sstevel@tonic-gate if (!(((CK_LONG)(attrs[i].ulValueLen)) > 0)) {
8107c478bd9Sstevel@tonic-gate /* if it isn't an optional attr, len should be > 0 */
8117c478bd9Sstevel@tonic-gate if (!object->attributes[i].canBeEmptyValue) {
8127c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
8137c478bd9Sstevel@tonic-gate goto finish;
8147c478bd9Sstevel@tonic-gate }
8157c478bd9Sstevel@tonic-gate } else {
8167c478bd9Sstevel@tonic-gate attrs_with_val[num_attrs_with_val].type = attrs[i].type;
8177c478bd9Sstevel@tonic-gate attrs_with_val[num_attrs_with_val].ulValueLen =
8187c478bd9Sstevel@tonic-gate attrs[i].ulValueLen;
8197c478bd9Sstevel@tonic-gate attrs_with_val[num_attrs_with_val].pValue =
8207c478bd9Sstevel@tonic-gate malloc(attrs[i].ulValueLen);
8217c478bd9Sstevel@tonic-gate if (attrs_with_val[num_attrs_with_val].pValue == NULL) {
8227c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
8237c478bd9Sstevel@tonic-gate goto finish;
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate num_attrs_with_val++;
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate }
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
8307c478bd9Sstevel@tonic-gate slot_object->hObject, attrs_with_val, num_attrs_with_val);
8317c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
8327c478bd9Sstevel@tonic-gate goto finish;
8337c478bd9Sstevel@tonic-gate }
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate /* store these values into the meta object */
8367c478bd9Sstevel@tonic-gate for (i = 0; i < num_attrs_with_val; i++) {
8377c478bd9Sstevel@tonic-gate rv = attribute_set_value(&(attrs_with_val[i]),
8387c478bd9Sstevel@tonic-gate object->attributes, object->num_attributes);
8397c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
8407c478bd9Sstevel@tonic-gate goto finish;
8417c478bd9Sstevel@tonic-gate }
8427c478bd9Sstevel@tonic-gate }
8437c478bd9Sstevel@tonic-gate
8447c478bd9Sstevel@tonic-gate finish:
8457c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&object->attribute_lock);
8467c478bd9Sstevel@tonic-gate
8477c478bd9Sstevel@tonic-gate if (session)
8487c478bd9Sstevel@tonic-gate meta_release_slot_session(session);
8497c478bd9Sstevel@tonic-gate
8507c478bd9Sstevel@tonic-gate if (attrs) {
8517c478bd9Sstevel@tonic-gate for (i = 0; i < num_attrs; i++) {
8527c478bd9Sstevel@tonic-gate if (attrs[i].pValue != NULL) {
8537c478bd9Sstevel@tonic-gate free(attrs[i].pValue);
8547c478bd9Sstevel@tonic-gate }
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate free(attrs);
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate if (attrs_with_val) {
8607c478bd9Sstevel@tonic-gate for (i = 0; i < num_attrs; i++) {
8617c478bd9Sstevel@tonic-gate if (attrs_with_val[i].pValue != NULL) {
8627c478bd9Sstevel@tonic-gate free(attrs_with_val[i].pValue);
8637c478bd9Sstevel@tonic-gate }
8647c478bd9Sstevel@tonic-gate }
8657c478bd9Sstevel@tonic-gate free(attrs_with_val);
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate return (rv);
8687c478bd9Sstevel@tonic-gate }
8697c478bd9Sstevel@tonic-gate
8707c478bd9Sstevel@tonic-gate /*
8717c478bd9Sstevel@tonic-gate * Create an object to be used for wrapping and unwrapping.
8727c478bd9Sstevel@tonic-gate * The same template will be used for all wrapping/unwrapping keys all
8737c478bd9Sstevel@tonic-gate * the time
8747c478bd9Sstevel@tonic-gate */
8757c478bd9Sstevel@tonic-gate
8767c478bd9Sstevel@tonic-gate static CK_RV
create_wrap_unwrap_key(slot_session_t * slot_session,CK_OBJECT_HANDLE * hObject,wrap_info_t * wrap_info,char * key_data,CK_ULONG key_len)8777c478bd9Sstevel@tonic-gate create_wrap_unwrap_key(slot_session_t *slot_session, CK_OBJECT_HANDLE *hObject,
8787c478bd9Sstevel@tonic-gate wrap_info_t *wrap_info, char *key_data, CK_ULONG key_len)
8797c478bd9Sstevel@tonic-gate {
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate CK_OBJECT_CLASS objclass;
8827c478bd9Sstevel@tonic-gate CK_KEY_TYPE keytype;
8837c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
8847c478bd9Sstevel@tonic-gate int i;
8857c478bd9Sstevel@tonic-gate CK_ATTRIBUTE template[WRAP_KEY_TEMPLATE_SIZE];
8867c478bd9Sstevel@tonic-gate
8877c478bd9Sstevel@tonic-gate i = 0;
8887c478bd9Sstevel@tonic-gate objclass = wrap_info->class;
8897c478bd9Sstevel@tonic-gate template[i].type = CKA_CLASS;
8907c478bd9Sstevel@tonic-gate template[i].pValue = &objclass;
8917c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (objclass);
8927c478bd9Sstevel@tonic-gate
8937c478bd9Sstevel@tonic-gate i++;
8947c478bd9Sstevel@tonic-gate keytype = wrap_info->key_type;
8957c478bd9Sstevel@tonic-gate template[i].type = CKA_KEY_TYPE;
8967c478bd9Sstevel@tonic-gate template[i].pValue = &keytype;
8977c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (keytype);
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate i++;
9007c478bd9Sstevel@tonic-gate template[i].type = CKA_TOKEN;
9017c478bd9Sstevel@tonic-gate template[i].pValue = &falsevalue;
9027c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (falsevalue);
9037c478bd9Sstevel@tonic-gate
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate if (objclass == CKO_SECRET_KEY) {
9067c478bd9Sstevel@tonic-gate i++;
9077c478bd9Sstevel@tonic-gate template[i].type = CKA_VALUE;
9087c478bd9Sstevel@tonic-gate template[i].pValue = key_data;
9097c478bd9Sstevel@tonic-gate template[i].ulValueLen = key_len;
9107c478bd9Sstevel@tonic-gate
9117c478bd9Sstevel@tonic-gate i++;
9127c478bd9Sstevel@tonic-gate template[i].type = CKA_WRAP;
9137c478bd9Sstevel@tonic-gate template[i].pValue = &truevalue;
9147c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (truevalue);
9157c478bd9Sstevel@tonic-gate
9167c478bd9Sstevel@tonic-gate i++;
9177c478bd9Sstevel@tonic-gate template[i].type = CKA_UNWRAP;
9187c478bd9Sstevel@tonic-gate template[i].pValue = &truevalue;
9197c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (truevalue);
9207c478bd9Sstevel@tonic-gate } else {
9217c478bd9Sstevel@tonic-gate /* Modulus is the same for rsa public and private key */
9227c478bd9Sstevel@tonic-gate i++;
9237c478bd9Sstevel@tonic-gate template[i].type = CKA_MODULUS;
9247c478bd9Sstevel@tonic-gate template[i].pValue = Modulus;
9257c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (Modulus);
9267c478bd9Sstevel@tonic-gate
9277c478bd9Sstevel@tonic-gate if (objclass == CKO_PUBLIC_KEY) {
9287c478bd9Sstevel@tonic-gate /* RSA public key */
9297c478bd9Sstevel@tonic-gate i++;
9307c478bd9Sstevel@tonic-gate template[i].type = CKA_PUBLIC_EXPONENT;
9317c478bd9Sstevel@tonic-gate template[i].pValue = PubExpo;
9327c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (PubExpo);
9337c478bd9Sstevel@tonic-gate
9347c478bd9Sstevel@tonic-gate i++;
9357c478bd9Sstevel@tonic-gate template[i].type = CKA_WRAP;
9367c478bd9Sstevel@tonic-gate template[i].pValue = &truevalue;
9377c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (truevalue);
9387c478bd9Sstevel@tonic-gate } else {
9397c478bd9Sstevel@tonic-gate /* RSA private key */
9407c478bd9Sstevel@tonic-gate i++;
9417c478bd9Sstevel@tonic-gate template[i].type = CKA_PRIVATE_EXPONENT;
9427c478bd9Sstevel@tonic-gate template[i].pValue = PriExpo;
9437c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (PriExpo);
9447c478bd9Sstevel@tonic-gate
9457c478bd9Sstevel@tonic-gate i++;
9467c478bd9Sstevel@tonic-gate template[i].type = CKA_UNWRAP;
9477c478bd9Sstevel@tonic-gate template[i].pValue = &truevalue;
9487c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (truevalue);
9497c478bd9Sstevel@tonic-gate }
9507c478bd9Sstevel@tonic-gate }
9517c478bd9Sstevel@tonic-gate
9527c478bd9Sstevel@tonic-gate rv = FUNCLIST(slot_session->fw_st_id)->C_CreateObject(
9537c478bd9Sstevel@tonic-gate slot_session->hSession, template, i + 1, hObject);
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate return (rv);
9567c478bd9Sstevel@tonic-gate }
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate
9597c478bd9Sstevel@tonic-gate /*
9607c478bd9Sstevel@tonic-gate * Create a clone of a non-sensitive and extractable object.
9617c478bd9Sstevel@tonic-gate * If the template required for creating the clone doesn't exist,
9627c478bd9Sstevel@tonic-gate * it will be retrieved from the master clone.
9637c478bd9Sstevel@tonic-gate */
9647c478bd9Sstevel@tonic-gate static CK_RV
clone_by_create(meta_object_t * object,slot_object_t * new_clone,slot_session_t * dst_slot_session)9657c478bd9Sstevel@tonic-gate clone_by_create(meta_object_t *object, slot_object_t *new_clone,
9667c478bd9Sstevel@tonic-gate slot_session_t *dst_slot_session)
9677c478bd9Sstevel@tonic-gate {
9687c478bd9Sstevel@tonic-gate CK_RV rv;
969034448feSmcpowers int free_token_index = -1;
9707c478bd9Sstevel@tonic-gate
9717c478bd9Sstevel@tonic-gate if (object->attributes == NULL) {
9727c478bd9Sstevel@tonic-gate rv = meta_object_copyin(object);
9737c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
9747c478bd9Sstevel@tonic-gate return (rv);
9757c478bd9Sstevel@tonic-gate }
9767c478bd9Sstevel@tonic-gate }
9777c478bd9Sstevel@tonic-gate
9787c478bd9Sstevel@tonic-gate if (object->clone_template == NULL) {
9797c478bd9Sstevel@tonic-gate rv = meta_clone_template_setup(object, object->attributes,
9807c478bd9Sstevel@tonic-gate object->num_attributes);
9817c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
9827c478bd9Sstevel@tonic-gate return (rv);
9837c478bd9Sstevel@tonic-gate }
9847c478bd9Sstevel@tonic-gate }
9857c478bd9Sstevel@tonic-gate
986034448feSmcpowers if (object->isFreeToken == FREE_ENABLED) {
987034448feSmcpowers if (dst_slot_session->slotnum == get_keystore_slotnum())
988034448feSmcpowers free_token_index = set_template_boolean(CKA_TOKEN,
989034448feSmcpowers object->clone_template,
990034448feSmcpowers object->clone_template_size, B_FALSE, &truevalue);
991034448feSmcpowers else
992034448feSmcpowers free_token_index = set_template_boolean(CKA_TOKEN,
993034448feSmcpowers object->clone_template,
994034448feSmcpowers object->clone_template_size, B_FALSE, &falsevalue);
995034448feSmcpowers }
996034448feSmcpowers
9977c478bd9Sstevel@tonic-gate /* Create the clone... */
9987c478bd9Sstevel@tonic-gate rv = FUNCLIST(dst_slot_session->fw_st_id)->C_CreateObject(
9997c478bd9Sstevel@tonic-gate dst_slot_session->hSession, object->clone_template,
10007c478bd9Sstevel@tonic-gate object->clone_template_size, &(new_clone->hObject));
1001034448feSmcpowers
1002034448feSmcpowers if (free_token_index != -1) {
1003d3a28a55Sdinak free_token_index = set_template_boolean(CKA_TOKEN,
1004d3a28a55Sdinak object->clone_template, object->clone_template_size,
1005034448feSmcpowers B_FALSE, &falsevalue);
1006034448feSmcpowers }
1007034448feSmcpowers
10087c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
10097c478bd9Sstevel@tonic-gate return (rv);
10107c478bd9Sstevel@tonic-gate }
10117c478bd9Sstevel@tonic-gate
10127c478bd9Sstevel@tonic-gate return (CKR_OK);
10137c478bd9Sstevel@tonic-gate }
10147c478bd9Sstevel@tonic-gate
10157c478bd9Sstevel@tonic-gate /*
10167c478bd9Sstevel@tonic-gate * Goes through the list of wraping mechanisms, and returns the first
10177c478bd9Sstevel@tonic-gate * one that is supported by both the source and the destination slot.
10187c478bd9Sstevel@tonic-gate * If none of the mechanisms are supported by both slot, return the
10197c478bd9Sstevel@tonic-gate * first mechanism that's supported by the source slot
10207c478bd9Sstevel@tonic-gate */
10217c478bd9Sstevel@tonic-gate static CK_RV
find_best_match_wrap_mech(wrap_info_t * wrap_info,int num_info,CK_ULONG src_slotnum,CK_ULONG dst_slotnum,int * first_both_mech,int * first_src_mech)10227c478bd9Sstevel@tonic-gate find_best_match_wrap_mech(wrap_info_t *wrap_info, int num_info,
10237c478bd9Sstevel@tonic-gate CK_ULONG src_slotnum, CK_ULONG dst_slotnum, int *first_both_mech,
10247c478bd9Sstevel@tonic-gate int *first_src_mech)
10257c478bd9Sstevel@tonic-gate {
10267c478bd9Sstevel@tonic-gate
10277c478bd9Sstevel@tonic-gate int i;
10287c478bd9Sstevel@tonic-gate boolean_t src_supports, dst_supports;
10297c478bd9Sstevel@tonic-gate CK_RV rv;
1030d3a28a55Sdinak CK_MECHANISM_INFO mech_info;
1031d3a28a55Sdinak
1032d3a28a55Sdinak mech_info.flags = CKF_WRAP;
10337c478bd9Sstevel@tonic-gate
10347c478bd9Sstevel@tonic-gate for (i = 0; i < num_info; i++) {
10357c478bd9Sstevel@tonic-gate src_supports = B_FALSE;
10367c478bd9Sstevel@tonic-gate dst_supports = B_FALSE;
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate rv = meta_mechManager_slot_supports_mech(
10397c478bd9Sstevel@tonic-gate (wrap_info[i]).mech_type, src_slotnum,
1040d3a28a55Sdinak &src_supports, NULL, B_FALSE, &mech_info);
10417c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
10427c478bd9Sstevel@tonic-gate return (rv);
10437c478bd9Sstevel@tonic-gate }
10447c478bd9Sstevel@tonic-gate
10457c478bd9Sstevel@tonic-gate rv = meta_mechManager_slot_supports_mech(
10467c478bd9Sstevel@tonic-gate (wrap_info[i]).mech_type, dst_slotnum,
1047d3a28a55Sdinak &dst_supports, NULL, B_FALSE, &mech_info);
10487c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
10497c478bd9Sstevel@tonic-gate return (rv);
10507c478bd9Sstevel@tonic-gate }
10517c478bd9Sstevel@tonic-gate
10527c478bd9Sstevel@tonic-gate /* both source and destination supports the mech */
10537c478bd9Sstevel@tonic-gate if ((src_supports) && (dst_supports)) {
10547c478bd9Sstevel@tonic-gate *first_both_mech = i;
10557c478bd9Sstevel@tonic-gate return (CKR_OK);
10567c478bd9Sstevel@tonic-gate }
10577c478bd9Sstevel@tonic-gate
10587c478bd9Sstevel@tonic-gate if ((src_supports) && (*first_src_mech == -1)) {
10597c478bd9Sstevel@tonic-gate *first_src_mech = i;
10607c478bd9Sstevel@tonic-gate }
10617c478bd9Sstevel@tonic-gate }
10627c478bd9Sstevel@tonic-gate return (CKR_OK);
10637c478bd9Sstevel@tonic-gate }
10647c478bd9Sstevel@tonic-gate
10657c478bd9Sstevel@tonic-gate /*
10667c478bd9Sstevel@tonic-gate * Determine the wrapping/unwrapping mechanism to be used
10677c478bd9Sstevel@tonic-gate *
10687c478bd9Sstevel@tonic-gate * If possible, select a mechanism that's supported by both source
10697c478bd9Sstevel@tonic-gate * and destination slot. If none of the mechanisms are supported
10707c478bd9Sstevel@tonic-gate * by both slot, then, select the first one supported by
10717c478bd9Sstevel@tonic-gate * the source slot.
10727c478bd9Sstevel@tonic-gate */
10737c478bd9Sstevel@tonic-gate
10747c478bd9Sstevel@tonic-gate static CK_RV
get_wrap_mechanism(CK_OBJECT_CLASS obj_class,CK_KEY_TYPE key_type,CK_ULONG src_slotnum,CK_ULONG dst_slotnum,wrap_info_t * wrap_info)10757c478bd9Sstevel@tonic-gate get_wrap_mechanism(CK_OBJECT_CLASS obj_class, CK_KEY_TYPE key_type,
10767c478bd9Sstevel@tonic-gate CK_ULONG src_slotnum, CK_ULONG dst_slotnum, wrap_info_t *wrap_info)
10777c478bd9Sstevel@tonic-gate {
10787c478bd9Sstevel@tonic-gate wrap_info_t *wrap_info_to_search = NULL;
10797c478bd9Sstevel@tonic-gate unsigned int num_wrap_info;
10807c478bd9Sstevel@tonic-gate CK_RV rv;
10817c478bd9Sstevel@tonic-gate int i;
10827c478bd9Sstevel@tonic-gate boolean_t src_supports = B_FALSE, dst_supports = B_FALSE;
10837c478bd9Sstevel@tonic-gate int first_src_mech, rsa_first_src_mech, first_both_mech;
1084d3a28a55Sdinak CK_MECHANISM_INFO mech_info;
1085d3a28a55Sdinak
1086d3a28a55Sdinak mech_info.flags = CKF_WRAP;
10877c478bd9Sstevel@tonic-gate
10887c478bd9Sstevel@tonic-gate if ((obj_class == CKO_PRIVATE_KEY) && (key_type == CKK_KEA)) {
10897c478bd9Sstevel@tonic-gate /*
10907c478bd9Sstevel@tonic-gate * only SKIPJACK keys can be used for wrapping
10917c478bd9Sstevel@tonic-gate * KEA private keys
10927c478bd9Sstevel@tonic-gate */
10937c478bd9Sstevel@tonic-gate
10947c478bd9Sstevel@tonic-gate for (i = 0; i < num_special_wrap_info; i++) {
10957c478bd9Sstevel@tonic-gate if ((special_wrap_info[i]).mech_type
10967c478bd9Sstevel@tonic-gate != CKM_SKIPJACK_WRAP) {
10977c478bd9Sstevel@tonic-gate continue;
10987c478bd9Sstevel@tonic-gate }
10997c478bd9Sstevel@tonic-gate
11007c478bd9Sstevel@tonic-gate src_supports = B_FALSE;
11017c478bd9Sstevel@tonic-gate dst_supports = B_FALSE;
11027c478bd9Sstevel@tonic-gate
11037c478bd9Sstevel@tonic-gate rv = meta_mechManager_slot_supports_mech(
11047c478bd9Sstevel@tonic-gate (special_wrap_info[i]).mech_type, src_slotnum,
1105d3a28a55Sdinak &src_supports, NULL, B_FALSE, &mech_info);
11067c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
11077c478bd9Sstevel@tonic-gate goto finish;
11087c478bd9Sstevel@tonic-gate }
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate rv = meta_mechManager_slot_supports_mech(
11117c478bd9Sstevel@tonic-gate (special_wrap_info[i]).mech_type, dst_slotnum,
1112d3a28a55Sdinak &dst_supports, NULL, B_FALSE, &mech_info);
11137c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
11147c478bd9Sstevel@tonic-gate goto finish;
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate if (src_supports) {
11187c478bd9Sstevel@tonic-gate /*
11197c478bd9Sstevel@tonic-gate * both src and dst supports the mech or
11207c478bd9Sstevel@tonic-gate * only the src supports the mech
11217c478bd9Sstevel@tonic-gate */
11227c478bd9Sstevel@tonic-gate (void) memcpy(wrap_info,
11237c478bd9Sstevel@tonic-gate &(special_wrap_info[i]),
11247c478bd9Sstevel@tonic-gate sizeof (wrap_info_t));
11257c478bd9Sstevel@tonic-gate
11267c478bd9Sstevel@tonic-gate wrap_info->src_supports = src_supports;
11277c478bd9Sstevel@tonic-gate wrap_info->dst_supports = dst_supports;
11287c478bd9Sstevel@tonic-gate rv = CKR_OK;
11297c478bd9Sstevel@tonic-gate goto finish;
11307c478bd9Sstevel@tonic-gate }
11317c478bd9Sstevel@tonic-gate
11327c478bd9Sstevel@tonic-gate }
11337c478bd9Sstevel@tonic-gate
11347c478bd9Sstevel@tonic-gate /*
11357c478bd9Sstevel@tonic-gate * if we are here, that means neither the source slot
1136*5893fa69SDan OpenSolaris Anderson * nor the destination slots supports CKM_SKIPJACK_WRAP.
11377c478bd9Sstevel@tonic-gate */
11387c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
11397c478bd9Sstevel@tonic-gate goto finish;
11407c478bd9Sstevel@tonic-gate }
11417c478bd9Sstevel@tonic-gate
11427c478bd9Sstevel@tonic-gate if ((key_type == CKK_SKIPJACK) || (key_type == CKK_BATON) ||
11437c478bd9Sstevel@tonic-gate (key_type == CKK_JUNIPER)) {
11447c478bd9Sstevel@tonic-gate /* special key types */
11457c478bd9Sstevel@tonic-gate wrap_info_to_search = special_wrap_info;
11467c478bd9Sstevel@tonic-gate num_wrap_info = num_special_wrap_info;
11477c478bd9Sstevel@tonic-gate } else {
11487c478bd9Sstevel@tonic-gate /* use the regular wrapping mechanisms */
11497c478bd9Sstevel@tonic-gate wrap_info_to_search = common_wrap_info;
11507c478bd9Sstevel@tonic-gate num_wrap_info = num_common_wrap_info;
11517c478bd9Sstevel@tonic-gate }
11527c478bd9Sstevel@tonic-gate
11537c478bd9Sstevel@tonic-gate first_both_mech = -1;
11547c478bd9Sstevel@tonic-gate first_src_mech = -1;
11557c478bd9Sstevel@tonic-gate
11567c478bd9Sstevel@tonic-gate rv = find_best_match_wrap_mech(wrap_info_to_search, num_wrap_info,
11577c478bd9Sstevel@tonic-gate src_slotnum, dst_slotnum, &first_both_mech, &first_src_mech);
11587c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
11597c478bd9Sstevel@tonic-gate goto finish;
11607c478bd9Sstevel@tonic-gate }
11617c478bd9Sstevel@tonic-gate
11627c478bd9Sstevel@tonic-gate if (first_both_mech != -1) {
11637c478bd9Sstevel@tonic-gate (void) memcpy(wrap_info,
11647c478bd9Sstevel@tonic-gate &(wrap_info_to_search[first_both_mech]),
11657c478bd9Sstevel@tonic-gate sizeof (wrap_info_t));
11667c478bd9Sstevel@tonic-gate
11677c478bd9Sstevel@tonic-gate wrap_info->src_supports = B_TRUE;
11687c478bd9Sstevel@tonic-gate wrap_info->dst_supports = B_TRUE;
11697c478bd9Sstevel@tonic-gate rv = CKR_OK;
11707c478bd9Sstevel@tonic-gate goto finish;
11717c478bd9Sstevel@tonic-gate }
11727c478bd9Sstevel@tonic-gate
11737c478bd9Sstevel@tonic-gate /*
11747c478bd9Sstevel@tonic-gate * If we are here, we did not find a mechanism that's supported
11757c478bd9Sstevel@tonic-gate * by both source and destination slot.
11767c478bd9Sstevel@tonic-gate *
11777c478bd9Sstevel@tonic-gate * If it is a secret key, can also try to wrap it with
11787c478bd9Sstevel@tonic-gate * a RSA public key
11797c478bd9Sstevel@tonic-gate */
11807c478bd9Sstevel@tonic-gate if (obj_class == CKO_SECRET_KEY) {
11817c478bd9Sstevel@tonic-gate first_both_mech = -1;
11827c478bd9Sstevel@tonic-gate rsa_first_src_mech = -1;
11837c478bd9Sstevel@tonic-gate
11847c478bd9Sstevel@tonic-gate rv = find_best_match_wrap_mech(rsa_wrap_info,
11857c478bd9Sstevel@tonic-gate num_rsa_wrap_info, src_slotnum, dst_slotnum,
11867c478bd9Sstevel@tonic-gate &first_both_mech, &rsa_first_src_mech);
11877c478bd9Sstevel@tonic-gate
11887c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
11897c478bd9Sstevel@tonic-gate goto finish;
11907c478bd9Sstevel@tonic-gate }
11917c478bd9Sstevel@tonic-gate
11927c478bd9Sstevel@tonic-gate if (first_both_mech > -1) {
11937c478bd9Sstevel@tonic-gate (void) memcpy(wrap_info,
11947c478bd9Sstevel@tonic-gate &(rsa_wrap_info[first_both_mech]),
11957c478bd9Sstevel@tonic-gate sizeof (wrap_info_t));
11967c478bd9Sstevel@tonic-gate
11977c478bd9Sstevel@tonic-gate wrap_info->src_supports = B_TRUE;
11987c478bd9Sstevel@tonic-gate wrap_info->dst_supports = B_TRUE;
11997c478bd9Sstevel@tonic-gate rv = CKR_OK;
12007c478bd9Sstevel@tonic-gate goto finish;
12017c478bd9Sstevel@tonic-gate }
12027c478bd9Sstevel@tonic-gate }
12037c478bd9Sstevel@tonic-gate
12047c478bd9Sstevel@tonic-gate /*
12057c478bd9Sstevel@tonic-gate * if we are here, that means none of the mechanisms are supported
12067c478bd9Sstevel@tonic-gate * by both the source and the destination
12077c478bd9Sstevel@tonic-gate */
12087c478bd9Sstevel@tonic-gate if (first_src_mech > -1) {
12097c478bd9Sstevel@tonic-gate /* source slot support one of the secret key mechs */
12107c478bd9Sstevel@tonic-gate (void) memcpy(wrap_info,
12117c478bd9Sstevel@tonic-gate &(wrap_info_to_search[first_src_mech]),
12127c478bd9Sstevel@tonic-gate sizeof (wrap_info_t));
12137c478bd9Sstevel@tonic-gate wrap_info->src_supports = B_TRUE;
12147c478bd9Sstevel@tonic-gate wrap_info->dst_supports = B_FALSE;
12157c478bd9Sstevel@tonic-gate rv = CKR_OK;
12167c478bd9Sstevel@tonic-gate } else if (rsa_first_src_mech > -1) {
12177c478bd9Sstevel@tonic-gate /* source slot support one of the RSA mechs */
12187c478bd9Sstevel@tonic-gate (void) memcpy(wrap_info, &(rsa_wrap_info[rsa_first_src_mech]),
12197c478bd9Sstevel@tonic-gate sizeof (wrap_info_t));
12207c478bd9Sstevel@tonic-gate
12217c478bd9Sstevel@tonic-gate wrap_info->src_supports = B_TRUE;
12227c478bd9Sstevel@tonic-gate wrap_info->dst_supports = B_FALSE;
12237c478bd9Sstevel@tonic-gate rv = CKR_OK;
12247c478bd9Sstevel@tonic-gate } else {
12257c478bd9Sstevel@tonic-gate /* neither source nor destination support any wrap mechs */
12267c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
12277c478bd9Sstevel@tonic-gate }
12287c478bd9Sstevel@tonic-gate
12297c478bd9Sstevel@tonic-gate finish:
12307c478bd9Sstevel@tonic-gate return (rv);
12317c478bd9Sstevel@tonic-gate }
12327c478bd9Sstevel@tonic-gate
12337c478bd9Sstevel@tonic-gate
12347c478bd9Sstevel@tonic-gate /*
12357c478bd9Sstevel@tonic-gate * This is called if the object to be cloned is a sensitive object
12367c478bd9Sstevel@tonic-gate */
12377c478bd9Sstevel@tonic-gate static CK_RV
clone_by_wrap(meta_object_t * object,slot_object_t * new_clone,slot_session_t * dst_slot_session)12387c478bd9Sstevel@tonic-gate clone_by_wrap(meta_object_t *object, slot_object_t *new_clone,
12397c478bd9Sstevel@tonic-gate slot_session_t *dst_slot_session)
12407c478bd9Sstevel@tonic-gate {
12417c478bd9Sstevel@tonic-gate slot_session_t *src_slot_session = NULL;
12427c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE wrappingKey = NULL, unwrappingKey = NULL;
12437c478bd9Sstevel@tonic-gate CK_MECHANISM wrappingMech;
12447c478bd9Sstevel@tonic-gate CK_BYTE *wrappedKey = NULL;
12457c478bd9Sstevel@tonic-gate CK_ULONG wrappedKeyLen = 0;
12467c478bd9Sstevel@tonic-gate slot_object_t *slot_object = NULL;
12477c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
12487c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE unwrapped_obj;
12497c478bd9Sstevel@tonic-gate meta_object_t *tmp_meta_obj = NULL;
12507c478bd9Sstevel@tonic-gate slot_object_t *tmp_slot_obj = NULL;
12517c478bd9Sstevel@tonic-gate CK_OBJECT_CLASS obj_class;
12527c478bd9Sstevel@tonic-gate CK_KEY_TYPE key_type;
12537c478bd9Sstevel@tonic-gate meta_session_t *tmp_meta_session = NULL;
12547c478bd9Sstevel@tonic-gate CK_ATTRIBUTE unwrap_template[4];
12557c478bd9Sstevel@tonic-gate char key_data[1024]; /* should be big enough for any key size */
12567c478bd9Sstevel@tonic-gate char ivbuf[1024]; /* should be big enough for any mech */
12577c478bd9Sstevel@tonic-gate wrap_info_t wrap_info;
12587c478bd9Sstevel@tonic-gate CK_ULONG key_len, unwrap_template_size;
12597c478bd9Sstevel@tonic-gate
12607c478bd9Sstevel@tonic-gate slot_object = object->clones[object->master_clone_slotnum];
12617c478bd9Sstevel@tonic-gate
12627c478bd9Sstevel@tonic-gate rv = meta_get_slot_session(object->master_clone_slotnum,
12637c478bd9Sstevel@tonic-gate &src_slot_session, object->creator_session->session_flags);
12647c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
12657c478bd9Sstevel@tonic-gate return (rv);
12667c478bd9Sstevel@tonic-gate }
12677c478bd9Sstevel@tonic-gate
12687c478bd9Sstevel@tonic-gate /*
12697c478bd9Sstevel@tonic-gate * get the object class and key type for unwrap template
12707c478bd9Sstevel@tonic-gate * This information will also be used for determining
12717c478bd9Sstevel@tonic-gate * which wrap mechanism and which key to use for
12727c478bd9Sstevel@tonic-gate * doing the wrapping
12737c478bd9Sstevel@tonic-gate */
12747c478bd9Sstevel@tonic-gate unwrap_template[0].type = CKA_CLASS;
12757c478bd9Sstevel@tonic-gate unwrap_template[0].pValue = &obj_class;
12767c478bd9Sstevel@tonic-gate unwrap_template[0].ulValueLen = sizeof (obj_class);
12777c478bd9Sstevel@tonic-gate
12787c478bd9Sstevel@tonic-gate unwrap_template[1].type = CKA_KEY_TYPE;
12797c478bd9Sstevel@tonic-gate unwrap_template[1].pValue = &key_type;
12807c478bd9Sstevel@tonic-gate unwrap_template[1].ulValueLen = sizeof (key_type);
12817c478bd9Sstevel@tonic-gate
12827c478bd9Sstevel@tonic-gate rv = FUNCLIST(src_slot_session->fw_st_id)->C_GetAttributeValue(
12837c478bd9Sstevel@tonic-gate src_slot_session->hSession, slot_object->hObject,
12847c478bd9Sstevel@tonic-gate unwrap_template, 2);
12857c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
12867c478bd9Sstevel@tonic-gate goto finish;
12877c478bd9Sstevel@tonic-gate }
12887c478bd9Sstevel@tonic-gate
12897c478bd9Sstevel@tonic-gate rv = get_wrap_mechanism(obj_class, key_type, src_slot_session->slotnum,
12907c478bd9Sstevel@tonic-gate dst_slot_session->slotnum, &wrap_info);
12917c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
12927c478bd9Sstevel@tonic-gate goto finish;
12937c478bd9Sstevel@tonic-gate }
12947c478bd9Sstevel@tonic-gate
12957c478bd9Sstevel@tonic-gate /*
12967b79d846SDina K Nimeh * read number of bytes required from random device for
12977c478bd9Sstevel@tonic-gate * creating a secret key for wrapping and unwrapping
12987c478bd9Sstevel@tonic-gate */
12997c478bd9Sstevel@tonic-gate if (wrap_info.class == CKO_SECRET_KEY) {
13007c478bd9Sstevel@tonic-gate
13017c478bd9Sstevel@tonic-gate /*
13027c478bd9Sstevel@tonic-gate * /dev/urandom will be used for generating the key used
13037c478bd9Sstevel@tonic-gate * for doing the wrap/unwrap. It's should be ok to
13047c478bd9Sstevel@tonic-gate * use /dev/urandom because this key is used for this
13057c478bd9Sstevel@tonic-gate * one time operation only. It doesn't need to be stored.
13067c478bd9Sstevel@tonic-gate */
13077c478bd9Sstevel@tonic-gate key_len = wrap_info.key_length;
13087b79d846SDina K Nimeh if (pkcs11_get_urandom(key_data, key_len) < 0) {
13097c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
13107c478bd9Sstevel@tonic-gate goto finish;
13117c478bd9Sstevel@tonic-gate }
13127c478bd9Sstevel@tonic-gate
13137c478bd9Sstevel@tonic-gate if (wrap_info.iv_length > 0) {
13147b79d846SDina K Nimeh if (pkcs11_get_urandom(
13157b79d846SDina K Nimeh ivbuf, wrap_info.iv_length) < 0) {
13167c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
13177c478bd9Sstevel@tonic-gate goto finish;
13187c478bd9Sstevel@tonic-gate }
13197c478bd9Sstevel@tonic-gate }
13207c478bd9Sstevel@tonic-gate }
13217c478bd9Sstevel@tonic-gate
13227c478bd9Sstevel@tonic-gate /* create the wrapping key */
13237c478bd9Sstevel@tonic-gate rv = create_wrap_unwrap_key(src_slot_session, &wrappingKey,
13247c478bd9Sstevel@tonic-gate &wrap_info, key_data, key_len);
13257c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
13267c478bd9Sstevel@tonic-gate goto finish;
13277c478bd9Sstevel@tonic-gate }
13287c478bd9Sstevel@tonic-gate
13297c478bd9Sstevel@tonic-gate wrappingMech.mechanism = wrap_info.mech_type;
13307c478bd9Sstevel@tonic-gate wrappingMech.pParameter = ((wrap_info.iv_length > 0) ? ivbuf : NULL);
13317c478bd9Sstevel@tonic-gate wrappingMech.ulParameterLen = wrap_info.iv_length;
13327c478bd9Sstevel@tonic-gate
13337c478bd9Sstevel@tonic-gate /* get the size of the wrapped key */
13347c478bd9Sstevel@tonic-gate rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
13357c478bd9Sstevel@tonic-gate src_slot_session->hSession, &wrappingMech,
13367c478bd9Sstevel@tonic-gate wrappingKey, slot_object->hObject, NULL, &wrappedKeyLen);
13377c478bd9Sstevel@tonic-gate
13387c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
13397c478bd9Sstevel@tonic-gate goto finish;
13407c478bd9Sstevel@tonic-gate }
13417c478bd9Sstevel@tonic-gate
13427c478bd9Sstevel@tonic-gate wrappedKey = malloc(wrappedKeyLen * sizeof (CK_BYTE));
13437c478bd9Sstevel@tonic-gate if (wrappedKey == NULL) {
13447c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
13457c478bd9Sstevel@tonic-gate goto finish;
13467c478bd9Sstevel@tonic-gate }
13477c478bd9Sstevel@tonic-gate
13487c478bd9Sstevel@tonic-gate /* do the actual key wrapping */
13497c478bd9Sstevel@tonic-gate rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
13507c478bd9Sstevel@tonic-gate src_slot_session->hSession, &wrappingMech,
13517c478bd9Sstevel@tonic-gate wrappingKey, slot_object->hObject, wrappedKey, &wrappedKeyLen);
13527c478bd9Sstevel@tonic-gate
13537c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
13547c478bd9Sstevel@tonic-gate goto finish;
13557c478bd9Sstevel@tonic-gate }
13567c478bd9Sstevel@tonic-gate
13577c478bd9Sstevel@tonic-gate /* explicitly force the unwrapped object to be not sensitive */
13587c478bd9Sstevel@tonic-gate unwrap_template[2].type = CKA_SENSITIVE;
13597c478bd9Sstevel@tonic-gate unwrap_template[2].pValue = &falsevalue;
13607c478bd9Sstevel@tonic-gate unwrap_template[2].ulValueLen = sizeof (falsevalue);
13617c478bd9Sstevel@tonic-gate
13627c478bd9Sstevel@tonic-gate unwrap_template[3].type = CKA_TOKEN;
13637c478bd9Sstevel@tonic-gate unwrap_template[3].pValue = &falsevalue;
13647c478bd9Sstevel@tonic-gate unwrap_template[3].ulValueLen = sizeof (falsevalue);
13657c478bd9Sstevel@tonic-gate
13667c478bd9Sstevel@tonic-gate unwrap_template_size =
13677c478bd9Sstevel@tonic-gate sizeof (unwrap_template) / sizeof (CK_ATTRIBUTE);
13687c478bd9Sstevel@tonic-gate
13697c478bd9Sstevel@tonic-gate if (!wrap_info.dst_supports) {
13707c478bd9Sstevel@tonic-gate /*
13717c478bd9Sstevel@tonic-gate * if we know for sure that the destination slot doesn't
13727c478bd9Sstevel@tonic-gate * support the wrapping mechanism, no point in trying.
13737c478bd9Sstevel@tonic-gate * go directly to unwrap in source slot, and create key
13747c478bd9Sstevel@tonic-gate * in destination
13757c478bd9Sstevel@tonic-gate */
13767c478bd9Sstevel@tonic-gate goto unwrap_in_source;
13777c478bd9Sstevel@tonic-gate }
13787c478bd9Sstevel@tonic-gate
13797c478bd9Sstevel@tonic-gate /* create the unwrapping key in destination slot */
13807c478bd9Sstevel@tonic-gate if (wrap_info.key_type == CKK_RSA) {
13817c478bd9Sstevel@tonic-gate /* for RSA key, the unwrapping key need to be private key */
13827c478bd9Sstevel@tonic-gate wrap_info.class = CKO_PRIVATE_KEY;
13837c478bd9Sstevel@tonic-gate }
13847c478bd9Sstevel@tonic-gate rv = create_wrap_unwrap_key(dst_slot_session,
13857c478bd9Sstevel@tonic-gate &unwrappingKey, &wrap_info, key_data, key_len);
13867c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
13877c478bd9Sstevel@tonic-gate goto finish;
13887c478bd9Sstevel@tonic-gate }
13897c478bd9Sstevel@tonic-gate
13907c478bd9Sstevel@tonic-gate rv = FUNCLIST(dst_slot_session->fw_st_id)->C_UnwrapKey(
13917c478bd9Sstevel@tonic-gate dst_slot_session->hSession, &wrappingMech,
13927c478bd9Sstevel@tonic-gate unwrappingKey, wrappedKey, wrappedKeyLen, unwrap_template,
13937c478bd9Sstevel@tonic-gate unwrap_template_size, &(new_clone->hObject));
13947c478bd9Sstevel@tonic-gate
13957c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
13967c478bd9Sstevel@tonic-gate unwrap_in_source:
13977c478bd9Sstevel@tonic-gate
13987c478bd9Sstevel@tonic-gate /*
13997c478bd9Sstevel@tonic-gate * There seemed to be a problem with unwrapping in the
14007c478bd9Sstevel@tonic-gate * destination slot.
14017c478bd9Sstevel@tonic-gate * Try to do the unwrap in the src slot so it becomes
14027c478bd9Sstevel@tonic-gate * a non-sensitive object, then, get all the attributes
14037c478bd9Sstevel@tonic-gate * and create the object in the destination slot
14047c478bd9Sstevel@tonic-gate */
14057c478bd9Sstevel@tonic-gate
14067c478bd9Sstevel@tonic-gate
14077c478bd9Sstevel@tonic-gate if (wrap_info.class == CKO_SECRET_KEY) {
14087c478bd9Sstevel@tonic-gate /* unwrap with same key used for wrapping */
14097c478bd9Sstevel@tonic-gate rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
14107c478bd9Sstevel@tonic-gate src_slot_session->hSession,
14117c478bd9Sstevel@tonic-gate &wrappingMech, wrappingKey, wrappedKey,
14127c478bd9Sstevel@tonic-gate wrappedKeyLen, unwrap_template,
14137c478bd9Sstevel@tonic-gate unwrap_template_size, &(unwrapped_obj));
14147c478bd9Sstevel@tonic-gate } else {
14157c478bd9Sstevel@tonic-gate /*
14167c478bd9Sstevel@tonic-gate * If the object is wrapping with RSA public key, need
14177c478bd9Sstevel@tonic-gate * need to create RSA private key for unwrapping
14187c478bd9Sstevel@tonic-gate */
14197c478bd9Sstevel@tonic-gate wrap_info.class = CKO_PRIVATE_KEY;
14207c478bd9Sstevel@tonic-gate rv = create_wrap_unwrap_key(src_slot_session,
14217c478bd9Sstevel@tonic-gate &unwrappingKey, &wrap_info, key_data, key_len);
14227c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
14237c478bd9Sstevel@tonic-gate goto finish;
14247c478bd9Sstevel@tonic-gate }
14257c478bd9Sstevel@tonic-gate rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
14267c478bd9Sstevel@tonic-gate src_slot_session->hSession,
14277c478bd9Sstevel@tonic-gate &wrappingMech, unwrappingKey, wrappedKey,
14287c478bd9Sstevel@tonic-gate wrappedKeyLen, unwrap_template,
14297c478bd9Sstevel@tonic-gate unwrap_template_size, &(unwrapped_obj));
14307c478bd9Sstevel@tonic-gate }
14317c478bd9Sstevel@tonic-gate
14327c478bd9Sstevel@tonic-gate
14337c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
14347c478bd9Sstevel@tonic-gate goto finish;
14357c478bd9Sstevel@tonic-gate }
14367c478bd9Sstevel@tonic-gate
14377c478bd9Sstevel@tonic-gate rv = meta_session_alloc(&tmp_meta_session);
14387c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
14397c478bd9Sstevel@tonic-gate goto finish;
14407c478bd9Sstevel@tonic-gate }
14417c478bd9Sstevel@tonic-gate
14427c478bd9Sstevel@tonic-gate tmp_meta_session->session_flags = CKF_SERIAL_SESSION;
14437c478bd9Sstevel@tonic-gate
14447c478bd9Sstevel@tonic-gate rv = meta_object_alloc(tmp_meta_session, &tmp_meta_obj);
14457c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
14467c478bd9Sstevel@tonic-gate goto finish;
14477c478bd9Sstevel@tonic-gate }
14487c478bd9Sstevel@tonic-gate
14497c478bd9Sstevel@tonic-gate rv = meta_slot_object_alloc(&tmp_slot_obj);
14507c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
14517c478bd9Sstevel@tonic-gate goto finish;
14527c478bd9Sstevel@tonic-gate }
14537c478bd9Sstevel@tonic-gate
14547c478bd9Sstevel@tonic-gate tmp_meta_obj->master_clone_slotnum = src_slot_session->slotnum;
14557c478bd9Sstevel@tonic-gate tmp_slot_obj->hObject = unwrapped_obj;
14567c478bd9Sstevel@tonic-gate tmp_meta_obj->clones[tmp_meta_obj->master_clone_slotnum]
14577c478bd9Sstevel@tonic-gate = tmp_slot_obj;
14587c478bd9Sstevel@tonic-gate meta_slot_object_activate(tmp_slot_obj, src_slot_session,
14597c478bd9Sstevel@tonic-gate B_FALSE);
14607c478bd9Sstevel@tonic-gate tmp_slot_obj = NULL;
14617c478bd9Sstevel@tonic-gate
14627c478bd9Sstevel@tonic-gate rv = clone_by_create(tmp_meta_obj, new_clone,
14637c478bd9Sstevel@tonic-gate dst_slot_session);
14647c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
14657c478bd9Sstevel@tonic-gate goto finish;
14667c478bd9Sstevel@tonic-gate }
14677c478bd9Sstevel@tonic-gate }
14687c478bd9Sstevel@tonic-gate
14697c478bd9Sstevel@tonic-gate finish:
14707c478bd9Sstevel@tonic-gate if (unwrappingKey) {
14717c478bd9Sstevel@tonic-gate (void) FUNCLIST(dst_slot_session->fw_st_id)->C_DestroyObject(
14727c478bd9Sstevel@tonic-gate dst_slot_session->hSession, unwrappingKey);
14737c478bd9Sstevel@tonic-gate }
14747c478bd9Sstevel@tonic-gate
14757c478bd9Sstevel@tonic-gate if (wrappingKey) {
14767c478bd9Sstevel@tonic-gate (void) FUNCLIST(src_slot_session->fw_st_id)->C_DestroyObject(
14777c478bd9Sstevel@tonic-gate src_slot_session->hSession, wrappingKey);
14787c478bd9Sstevel@tonic-gate }
14797c478bd9Sstevel@tonic-gate
14807c478bd9Sstevel@tonic-gate if (tmp_slot_obj) {
14817c478bd9Sstevel@tonic-gate (void) meta_slot_object_dealloc(tmp_slot_obj);
14827c478bd9Sstevel@tonic-gate }
14837c478bd9Sstevel@tonic-gate
14847c478bd9Sstevel@tonic-gate if (tmp_meta_obj) {
14858cae6764SAnthony Scarpino (void) meta_object_dealloc(tmp_meta_session, tmp_meta_obj,
14868cae6764SAnthony Scarpino B_TRUE);
14877c478bd9Sstevel@tonic-gate }
14887c478bd9Sstevel@tonic-gate
14897c478bd9Sstevel@tonic-gate if (tmp_meta_session) {
14907c478bd9Sstevel@tonic-gate (void) meta_session_dealloc(tmp_meta_session);
14917c478bd9Sstevel@tonic-gate }
14927c478bd9Sstevel@tonic-gate
14937c478bd9Sstevel@tonic-gate if (wrappedKey) {
14947c478bd9Sstevel@tonic-gate free(wrappedKey);
14957c478bd9Sstevel@tonic-gate }
14967c478bd9Sstevel@tonic-gate
14977c478bd9Sstevel@tonic-gate if (src_slot_session) {
14987c478bd9Sstevel@tonic-gate meta_release_slot_session(src_slot_session);
14997c478bd9Sstevel@tonic-gate }
15007c478bd9Sstevel@tonic-gate
15017c478bd9Sstevel@tonic-gate return (rv);
15027c478bd9Sstevel@tonic-gate
15037c478bd9Sstevel@tonic-gate }
15047c478bd9Sstevel@tonic-gate
15057c478bd9Sstevel@tonic-gate
15067c478bd9Sstevel@tonic-gate /*
15077c478bd9Sstevel@tonic-gate * meta_object_get_clone
15087c478bd9Sstevel@tonic-gate *
15097c478bd9Sstevel@tonic-gate * Creates a "clone" of a metaobject on the specified slot. A clone is a
15107c478bd9Sstevel@tonic-gate * copy of the object.
15117c478bd9Sstevel@tonic-gate *
1512*5893fa69SDan OpenSolaris Anderson * Clones are cached, so that they can be reused with subsequent operations.
15137c478bd9Sstevel@tonic-gate */
15147c478bd9Sstevel@tonic-gate CK_RV
meta_object_get_clone(meta_object_t * object,CK_ULONG slot_num,slot_session_t * slot_session,slot_object_t ** clone)15157c478bd9Sstevel@tonic-gate meta_object_get_clone(meta_object_t *object,
15167c478bd9Sstevel@tonic-gate CK_ULONG slot_num, slot_session_t *slot_session,
15177c478bd9Sstevel@tonic-gate slot_object_t **clone)
15187c478bd9Sstevel@tonic-gate {
15197c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
15207c478bd9Sstevel@tonic-gate slot_object_t *newclone = NULL;
15217c478bd9Sstevel@tonic-gate
15227c478bd9Sstevel@tonic-gate /* Does a clone already exist? */
15237c478bd9Sstevel@tonic-gate if (object->clones[slot_num] != NULL) {
15247c478bd9Sstevel@tonic-gate *clone = object->clones[slot_num];
15257c478bd9Sstevel@tonic-gate return (CKR_OK);
15267c478bd9Sstevel@tonic-gate }
15277c478bd9Sstevel@tonic-gate
15287c478bd9Sstevel@tonic-gate if ((object->isSensitive) && (object->isToken) &&
15297c478bd9Sstevel@tonic-gate (!metaslot_auto_key_migrate)) {
15307c478bd9Sstevel@tonic-gate /*
15317c478bd9Sstevel@tonic-gate * if the object is a sensitive token object, and auto
15327c478bd9Sstevel@tonic-gate * key migrate is not allowed, will not create the clone
15337c478bd9Sstevel@tonic-gate * in another slot
15347c478bd9Sstevel@tonic-gate */
15357c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
15367c478bd9Sstevel@tonic-gate }
15377c478bd9Sstevel@tonic-gate
15387c478bd9Sstevel@tonic-gate /* object attributes can't be extracted and attributes are not known */
15397c478bd9Sstevel@tonic-gate if ((!object->isExtractable) && (object->attributes == NULL)) {
15407c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
15417c478bd9Sstevel@tonic-gate }
15427c478bd9Sstevel@tonic-gate
15437c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&object->clone_create_lock);
15447c478bd9Sstevel@tonic-gate
15457c478bd9Sstevel@tonic-gate /* Maybe someone just created one? */
15467c478bd9Sstevel@tonic-gate if (object->clones[slot_num] != NULL) {
15477c478bd9Sstevel@tonic-gate *clone = object->clones[slot_num];
15487c478bd9Sstevel@tonic-gate goto finish;
15497c478bd9Sstevel@tonic-gate }
15507c478bd9Sstevel@tonic-gate
155189a7715aSkrishna /*
155289a7715aSkrishna * has an attempt already been made to create this object in
155389a7715aSkrishna * slot? If yes, and there's no clone, as indicated above,
155489a7715aSkrishna * that means this object can't be created in this slot.
155589a7715aSkrishna */
155689a7715aSkrishna if (object->tried_create_clone[slot_num]) {
155789a7715aSkrishna (void) pthread_mutex_unlock(&object->clone_create_lock);
155889a7715aSkrishna return (CKR_FUNCTION_FAILED);
155989a7715aSkrishna }
156089a7715aSkrishna
15617c478bd9Sstevel@tonic-gate rv = meta_slot_object_alloc(&newclone);
15627c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
15637c478bd9Sstevel@tonic-gate goto finish;
15647c478bd9Sstevel@tonic-gate
15657c478bd9Sstevel@tonic-gate object->tried_create_clone[slot_num] = B_TRUE;
15667c478bd9Sstevel@tonic-gate
1567034448feSmcpowers /*
1568034448feSmcpowers * If this object is sensitive and we do not have not copied in the
1569034448feSmcpowers * attributes via FreeObject functionality, then we need to wrap it off
1570034448feSmcpowers * the provider. If we do have attributes, we can just create the
1571034448feSmcpowers * clone
1572034448feSmcpowers */
1573034448feSmcpowers
1574034448feSmcpowers if (object->isSensitive && object->attributes == NULL) {
15757c478bd9Sstevel@tonic-gate rv = clone_by_wrap(object, newclone, slot_session);
15767c478bd9Sstevel@tonic-gate } else {
15777c478bd9Sstevel@tonic-gate rv = clone_by_create(object, newclone, slot_session);
15787c478bd9Sstevel@tonic-gate }
15797c478bd9Sstevel@tonic-gate
15807c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
15817c478bd9Sstevel@tonic-gate goto finish;
15827c478bd9Sstevel@tonic-gate }
15837c478bd9Sstevel@tonic-gate
15847c478bd9Sstevel@tonic-gate object->clones[slot_num] = newclone;
15857c478bd9Sstevel@tonic-gate meta_slot_object_activate(newclone, slot_session, object->isToken);
15867c478bd9Sstevel@tonic-gate
15877c478bd9Sstevel@tonic-gate *clone = newclone;
15887c478bd9Sstevel@tonic-gate newclone = NULL;
15897c478bd9Sstevel@tonic-gate finish:
15907c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&object->clone_create_lock);
15917c478bd9Sstevel@tonic-gate
15927c478bd9Sstevel@tonic-gate if (newclone)
15937c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(newclone);
15947c478bd9Sstevel@tonic-gate
15957c478bd9Sstevel@tonic-gate return (rv);
15967c478bd9Sstevel@tonic-gate }
15977c478bd9Sstevel@tonic-gate
15987c478bd9Sstevel@tonic-gate
15997c478bd9Sstevel@tonic-gate /*
16007c478bd9Sstevel@tonic-gate * meta_setup_clone_template
16017c478bd9Sstevel@tonic-gate *
16027c478bd9Sstevel@tonic-gate * Create a clone template for the specified object.
16037c478bd9Sstevel@tonic-gate */
16047c478bd9Sstevel@tonic-gate static CK_RV
meta_clone_template_setup(meta_object_t * object,const generic_attr_t * attributes,size_t num_attributes)16057c478bd9Sstevel@tonic-gate meta_clone_template_setup(meta_object_t *object,
16067c478bd9Sstevel@tonic-gate const generic_attr_t *attributes, size_t num_attributes)
16077c478bd9Sstevel@tonic-gate {
16087c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
16097c478bd9Sstevel@tonic-gate CK_ATTRIBUTE *clone_template;
16107c478bd9Sstevel@tonic-gate size_t i, c = 0;
16117c478bd9Sstevel@tonic-gate
16127c478bd9Sstevel@tonic-gate clone_template = malloc(num_attributes * sizeof (CK_ATTRIBUTE));
16137c478bd9Sstevel@tonic-gate if (clone_template == NULL) {
16147c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
16157c478bd9Sstevel@tonic-gate goto finish;
16167c478bd9Sstevel@tonic-gate }
16177c478bd9Sstevel@tonic-gate
16187c478bd9Sstevel@tonic-gate /* Don't allow attributes to change while we look at them. */
16197c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&object->attribute_lock);
16207c478bd9Sstevel@tonic-gate
16217c478bd9Sstevel@tonic-gate for (i = 0; i < num_attributes; i++) {
1622034448feSmcpowers if (!attributes[i].isCloneAttr ||
1623034448feSmcpowers (attributes[i].attribute.type == CKA_TOKEN &&
1624034448feSmcpowers object->isFreeToken == FREE_DISABLED)) {
16257c478bd9Sstevel@tonic-gate continue;
16267c478bd9Sstevel@tonic-gate }
16277c478bd9Sstevel@tonic-gate if ((!(attributes[i].hasValueForClone)) &&
16287c478bd9Sstevel@tonic-gate (attributes[i].canBeEmptyValue)) {
16297c478bd9Sstevel@tonic-gate continue;
16307c478bd9Sstevel@tonic-gate }
16317c478bd9Sstevel@tonic-gate
16327c478bd9Sstevel@tonic-gate clone_template[c].type = attributes[i].attribute.type;
16337c478bd9Sstevel@tonic-gate clone_template[c].ulValueLen =
16347c478bd9Sstevel@tonic-gate attributes[i].attribute.ulValueLen;
16357c478bd9Sstevel@tonic-gate /* Allocate space to store the attribute value. */
16367c478bd9Sstevel@tonic-gate clone_template[c].pValue = malloc(clone_template[c].ulValueLen);
16377c478bd9Sstevel@tonic-gate if (clone_template[c].pValue == NULL) {
1638*5893fa69SDan OpenSolaris Anderson free(clone_template);
16397c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY;
16407c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&object->attribute_lock);
16417c478bd9Sstevel@tonic-gate goto finish;
16427c478bd9Sstevel@tonic-gate }
16437c478bd9Sstevel@tonic-gate
16447c478bd9Sstevel@tonic-gate (void) memcpy(clone_template[c].pValue,
16457c478bd9Sstevel@tonic-gate object->attributes[i].attribute.pValue,
16467c478bd9Sstevel@tonic-gate clone_template[c].ulValueLen);
16477c478bd9Sstevel@tonic-gate c++;
16487c478bd9Sstevel@tonic-gate }
16497c478bd9Sstevel@tonic-gate
16507c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&object->attribute_lock);
16517c478bd9Sstevel@tonic-gate
16527c478bd9Sstevel@tonic-gate object->clone_template = clone_template;
16537c478bd9Sstevel@tonic-gate object->clone_template_size = c;
16547c478bd9Sstevel@tonic-gate
16557c478bd9Sstevel@tonic-gate finish:
16567c478bd9Sstevel@tonic-gate return (rv);
16577c478bd9Sstevel@tonic-gate }
16587c478bd9Sstevel@tonic-gate
16597c478bd9Sstevel@tonic-gate
16607c478bd9Sstevel@tonic-gate /*
16617c478bd9Sstevel@tonic-gate * meta_object_find_by_handle
16627c478bd9Sstevel@tonic-gate *
16637c478bd9Sstevel@tonic-gate * Search for an existing metaobject, using the object handle of a clone
16647c478bd9Sstevel@tonic-gate * on a particular slot.
16657c478bd9Sstevel@tonic-gate *
16667c478bd9Sstevel@tonic-gate * Returns a matching metaobject, or NULL if no match was found.
16677c478bd9Sstevel@tonic-gate */
16687c478bd9Sstevel@tonic-gate meta_object_t *
meta_object_find_by_handle(CK_OBJECT_HANDLE hObject,CK_ULONG slotnum,boolean_t token_only)16697c478bd9Sstevel@tonic-gate meta_object_find_by_handle(CK_OBJECT_HANDLE hObject, CK_ULONG slotnum,
16707c478bd9Sstevel@tonic-gate boolean_t token_only)
16717c478bd9Sstevel@tonic-gate {
16727c478bd9Sstevel@tonic-gate meta_object_t *object = NULL, *tmp_obj;
16737c478bd9Sstevel@tonic-gate meta_session_t *session;
16747c478bd9Sstevel@tonic-gate
16757c478bd9Sstevel@tonic-gate if (!token_only) {
16767c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&meta_sessionlist_lock);
16777c478bd9Sstevel@tonic-gate session = meta_sessionlist_head;
16787c478bd9Sstevel@tonic-gate while (session != NULL) {
16797c478bd9Sstevel@tonic-gate /* lock the objects list while we look at it */
16807c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(
16817c478bd9Sstevel@tonic-gate &(session->object_list_lock));
16827c478bd9Sstevel@tonic-gate tmp_obj = session->object_list_head;
16837c478bd9Sstevel@tonic-gate while (tmp_obj != NULL) {
16847c478bd9Sstevel@tonic-gate slot_object_t *slot_object;
16857c478bd9Sstevel@tonic-gate
16867c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(
16877c478bd9Sstevel@tonic-gate &(tmp_obj->object_lock));
16887c478bd9Sstevel@tonic-gate slot_object = tmp_obj->clones[slotnum];
16897c478bd9Sstevel@tonic-gate if (slot_object != NULL) {
16907c478bd9Sstevel@tonic-gate if (slot_object->hObject == hObject) {
16917c478bd9Sstevel@tonic-gate object = tmp_obj;
16927c478bd9Sstevel@tonic-gate }
16937c478bd9Sstevel@tonic-gate }
16947c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(
16957c478bd9Sstevel@tonic-gate &(tmp_obj->object_lock));
16967c478bd9Sstevel@tonic-gate if (object != NULL) {
16977c478bd9Sstevel@tonic-gate break;
16987c478bd9Sstevel@tonic-gate }
16997c478bd9Sstevel@tonic-gate tmp_obj = tmp_obj->next;
17007c478bd9Sstevel@tonic-gate }
17017c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(
17027c478bd9Sstevel@tonic-gate &(session->object_list_lock));
17037c478bd9Sstevel@tonic-gate if (object != NULL) {
17047c478bd9Sstevel@tonic-gate break;
17057c478bd9Sstevel@tonic-gate }
17067c478bd9Sstevel@tonic-gate session = session->next;
17077c478bd9Sstevel@tonic-gate }
17087c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&meta_sessionlist_lock);
17097c478bd9Sstevel@tonic-gate }
17107c478bd9Sstevel@tonic-gate
17117c478bd9Sstevel@tonic-gate if (object != NULL) {
17127c478bd9Sstevel@tonic-gate /* found the object, no need to look further */
17137c478bd9Sstevel@tonic-gate return (object);
17147c478bd9Sstevel@tonic-gate }
17157c478bd9Sstevel@tonic-gate
17167c478bd9Sstevel@tonic-gate /*
17177c478bd9Sstevel@tonic-gate * Look at list of token objects
17187c478bd9Sstevel@tonic-gate */
17197c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&tokenobject_list_lock);
17207c478bd9Sstevel@tonic-gate tmp_obj = tokenobject_list_head;
17217c478bd9Sstevel@tonic-gate
17227c478bd9Sstevel@tonic-gate while (tmp_obj != NULL) {
17237c478bd9Sstevel@tonic-gate slot_object_t *slot_object;
17247c478bd9Sstevel@tonic-gate
17257c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&(tmp_obj->object_lock));
17267c478bd9Sstevel@tonic-gate slot_object = tmp_obj->clones[slotnum];
17277c478bd9Sstevel@tonic-gate if (slot_object != NULL) {
17287c478bd9Sstevel@tonic-gate if (slot_object->hObject == hObject)
17297c478bd9Sstevel@tonic-gate object = tmp_obj;
17307c478bd9Sstevel@tonic-gate }
17317c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&(tmp_obj->object_lock));
17327c478bd9Sstevel@tonic-gate if (object != NULL) {
17337c478bd9Sstevel@tonic-gate break;
17347c478bd9Sstevel@tonic-gate }
17357c478bd9Sstevel@tonic-gate tmp_obj = tmp_obj->next;
17367c478bd9Sstevel@tonic-gate }
17377c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&tokenobject_list_lock);
17387c478bd9Sstevel@tonic-gate
17397c478bd9Sstevel@tonic-gate return (object);
17407c478bd9Sstevel@tonic-gate }
17417c478bd9Sstevel@tonic-gate
17427c478bd9Sstevel@tonic-gate CK_RV
meta_token_object_deactivate(token_obj_type_t token_type)17437c478bd9Sstevel@tonic-gate meta_token_object_deactivate(token_obj_type_t token_type)
17447c478bd9Sstevel@tonic-gate {
17457c478bd9Sstevel@tonic-gate meta_object_t *object, *tmp_object;
17467c478bd9Sstevel@tonic-gate CK_RV save_rv = CKR_OK, rv;
17477c478bd9Sstevel@tonic-gate
17487c478bd9Sstevel@tonic-gate /* get a write lock on the token object list */
17497c478bd9Sstevel@tonic-gate (void) pthread_rwlock_wrlock(&tokenobject_list_lock);
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate object = tokenobject_list_head;
17527c478bd9Sstevel@tonic-gate
17537c478bd9Sstevel@tonic-gate /* go through each object and delete the one with matching type */
17547c478bd9Sstevel@tonic-gate while (object != NULL) {
17557c478bd9Sstevel@tonic-gate tmp_object = object->next;
17567c478bd9Sstevel@tonic-gate
17577c478bd9Sstevel@tonic-gate if ((token_type == ALL_TOKEN) ||
17587c478bd9Sstevel@tonic-gate ((object->isPrivate) && (token_type == PRIVATE_TOKEN)) ||
17597c478bd9Sstevel@tonic-gate ((!object->isPrivate) && (token_type == PUBLIC_TOKEN))) {
17607c478bd9Sstevel@tonic-gate rv = meta_object_deactivate(object, B_TRUE, B_FALSE);
17617c478bd9Sstevel@tonic-gate if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
17627c478bd9Sstevel@tonic-gate save_rv = rv;
17637c478bd9Sstevel@tonic-gate goto finish;
17647c478bd9Sstevel@tonic-gate }
17658cae6764SAnthony Scarpino rv = meta_object_dealloc(NULL, object, B_FALSE);
17667c478bd9Sstevel@tonic-gate if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
17677c478bd9Sstevel@tonic-gate save_rv = rv;
17687c478bd9Sstevel@tonic-gate goto finish;
17697c478bd9Sstevel@tonic-gate }
17707c478bd9Sstevel@tonic-gate }
17717c478bd9Sstevel@tonic-gate object = tmp_object;
17727c478bd9Sstevel@tonic-gate }
17737c478bd9Sstevel@tonic-gate finish:
17747c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&tokenobject_list_lock);
17757c478bd9Sstevel@tonic-gate return (save_rv);
17767c478bd9Sstevel@tonic-gate }
17777c478bd9Sstevel@tonic-gate
17787c478bd9Sstevel@tonic-gate /*
17797c478bd9Sstevel@tonic-gate * This function adds the to-be-freed meta object to a linked list.
17807c478bd9Sstevel@tonic-gate * When the number of objects queued in the linked list reaches the
17817c478bd9Sstevel@tonic-gate * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
17827c478bd9Sstevel@tonic-gate * object (FIFO) in the list.
17837c478bd9Sstevel@tonic-gate */
17847c478bd9Sstevel@tonic-gate void
meta_object_delay_free(meta_object_t * objp)17857c478bd9Sstevel@tonic-gate meta_object_delay_free(meta_object_t *objp)
17867c478bd9Sstevel@tonic-gate {
17877c478bd9Sstevel@tonic-gate meta_object_t *tmp;
17887c478bd9Sstevel@tonic-gate
17897c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
17907c478bd9Sstevel@tonic-gate
17917c478bd9Sstevel@tonic-gate /* Add the newly deleted object at the end of the list */
17927c478bd9Sstevel@tonic-gate objp->next = NULL;
17937c478bd9Sstevel@tonic-gate if (obj_delay_freed.first == NULL) {
17947c478bd9Sstevel@tonic-gate obj_delay_freed.last = objp;
17957c478bd9Sstevel@tonic-gate obj_delay_freed.first = objp;
17967c478bd9Sstevel@tonic-gate } else {
17977c478bd9Sstevel@tonic-gate obj_delay_freed.last->next = objp;
17987c478bd9Sstevel@tonic-gate obj_delay_freed.last = objp;
17997c478bd9Sstevel@tonic-gate }
18007c478bd9Sstevel@tonic-gate
18017c478bd9Sstevel@tonic-gate if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
18027c478bd9Sstevel@tonic-gate /*
18037c478bd9Sstevel@tonic-gate * Free the first object in the list only if
18047c478bd9Sstevel@tonic-gate * the total count reaches maximum threshold.
18057c478bd9Sstevel@tonic-gate */
18067c478bd9Sstevel@tonic-gate obj_delay_freed.count--;
18077c478bd9Sstevel@tonic-gate tmp = obj_delay_freed.first->next;
18087c478bd9Sstevel@tonic-gate free(obj_delay_freed.first);
18097c478bd9Sstevel@tonic-gate obj_delay_freed.first = tmp;
18107c478bd9Sstevel@tonic-gate }
18117c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
18127c478bd9Sstevel@tonic-gate }
1813034448feSmcpowers
1814034448feSmcpowers
1815034448feSmcpowers /*
1816034448feSmcpowers * This function checks if the object passed can be a freeobject.
1817034448feSmcpowers *
1818034448feSmcpowers * If there is more than one provider that supports the supported freeobject
1819034448feSmcpowers * mechanisms then allow freeobjects to be an option.
1820034448feSmcpowers */
1821034448feSmcpowers
1822034448feSmcpowers boolean_t
meta_freeobject_check(meta_session_t * session,meta_object_t * object,CK_MECHANISM * pMech,CK_ATTRIBUTE * tmpl,CK_ULONG tmpl_len,CK_KEY_TYPE keytype)1823034448feSmcpowers meta_freeobject_check(meta_session_t *session, meta_object_t *object,
1824034448feSmcpowers CK_MECHANISM *pMech, CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len,
1825034448feSmcpowers CK_KEY_TYPE keytype)
1826034448feSmcpowers {
1827034448feSmcpowers mech_support_info_t *info = &(session->mech_support_info);
1828034448feSmcpowers
1829034448feSmcpowers /*
1830034448feSmcpowers * If key migration is turned off, or the object does not has any of
1831034448feSmcpowers * the required flags and there is only one slot, then we don't need
1832034448feSmcpowers * FreeObjects.
1833034448feSmcpowers */
1834034448feSmcpowers if (!metaslot_auto_key_migrate ||
1835034448feSmcpowers (!object->isToken && !object->isSensitive &&
1836034448feSmcpowers meta_slotManager_get_slotcount() < 2))
1837034448feSmcpowers goto failure;
1838034448feSmcpowers
1839034448feSmcpowers /*
1840034448feSmcpowers * If this call is for key generation, check pMech for supported
1841034448feSmcpowers * FreeObject mechs
1842034448feSmcpowers */
1843034448feSmcpowers if (pMech != NULL) {
1844034448feSmcpowers if (pMech->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN ||
1845034448feSmcpowers pMech->mechanism == CKM_EC_KEY_PAIR_GEN ||
1846034448feSmcpowers pMech->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN ||
1847034448feSmcpowers pMech->mechanism == CKM_DH_PKCS_DERIVE)
1848034448feSmcpowers info->mech = pMech->mechanism;
1849034448feSmcpowers else
1850034448feSmcpowers goto failure;
1851034448feSmcpowers
1852034448feSmcpowers /*
1853034448feSmcpowers * If this call is for an object creation, look inside the template
1854034448feSmcpowers * for supported FreeObject mechs
1855034448feSmcpowers */
1856034448feSmcpowers } else if (tmpl_len > 0) {
1857d3a28a55Sdinak if (!get_template_ulong(CKA_KEY_TYPE, tmpl, tmpl_len, &keytype))
1858034448feSmcpowers goto failure;
1859034448feSmcpowers
1860034448feSmcpowers switch (keytype) {
1861034448feSmcpowers case CKK_RSA:
1862034448feSmcpowers info->mech = CKM_RSA_PKCS_KEY_PAIR_GEN;
1863034448feSmcpowers break;
1864034448feSmcpowers case CKK_EC:
1865034448feSmcpowers info->mech = CKM_EC_KEY_PAIR_GEN;
1866034448feSmcpowers break;
1867034448feSmcpowers case CKK_DH:
1868034448feSmcpowers info->mech = CKM_DH_PKCS_KEY_PAIR_GEN;
1869034448feSmcpowers break;
1870034448feSmcpowers default:
1871034448feSmcpowers goto failure;
1872034448feSmcpowers }
1873034448feSmcpowers } else
1874034448feSmcpowers goto failure;
1875034448feSmcpowers
1876034448feSmcpowers /* Get the slot that support this mech... */
1877d3a28a55Sdinak if (meta_mechManager_get_slots(info, B_FALSE, NULL) != CKR_OK)
1878034448feSmcpowers goto failure;
1879034448feSmcpowers
1880034448feSmcpowers /*
1881034448feSmcpowers * If there is only one slot with the mech or the first slot in
1882034448feSmcpowers * the list is the keystore slot, we should bail.
1883034448feSmcpowers */
1884034448feSmcpowers if (info->num_supporting_slots < 2 &&
1885034448feSmcpowers info->supporting_slots[0]->slotnum == get_keystore_slotnum())
1886034448feSmcpowers goto failure;
1887034448feSmcpowers
1888034448feSmcpowers if (object->isToken)
1889034448feSmcpowers object->isFreeToken = FREE_ALLOWED_KEY;
1890034448feSmcpowers else
1891034448feSmcpowers object->isFreeToken = FREE_DISABLED;
1892034448feSmcpowers
1893034448feSmcpowers object->isFreeObject = FREE_ALLOWED_KEY;
1894034448feSmcpowers
1895034448feSmcpowers return (B_TRUE);
1896034448feSmcpowers
1897034448feSmcpowers failure:
1898034448feSmcpowers object->isFreeToken = FREE_DISABLED;
1899034448feSmcpowers object->isFreeObject = FREE_DISABLED;
1900034448feSmcpowers return (B_FALSE);
1901034448feSmcpowers }
1902034448feSmcpowers
1903034448feSmcpowers /*
1904034448feSmcpowers * This function assumes meta_freeobject_check() has just been called and set
1905034448feSmcpowers * the isFreeObject and/or isFreeToken vars to FREE_ALLOWED_KEY.
1906034448feSmcpowers *
1907034448feSmcpowers * If the template value for CKA_PRIVATE, CKA_SENSITIVE and/or CKA_TOKEN are
1908034448feSmcpowers * true, then isFreeObject is fully enabled. In addition isFreeToken is
1909034448feSmcpowers * enabled if is CKA_TOKEN true.
1910034448feSmcpowers *
1911034448feSmcpowers * If create is true, we are doing a C_CreateObject operation and don't
1912034448feSmcpowers * handle CKA_PRIVATE & CKA_SENSITIVE flags, we only care about CKA_TOKEN.
1913034448feSmcpowers */
1914034448feSmcpowers
1915034448feSmcpowers boolean_t
meta_freeobject_set(meta_object_t * object,CK_ATTRIBUTE * tmpl,CK_ULONG tmpl_len,boolean_t create)1916034448feSmcpowers meta_freeobject_set(meta_object_t *object, CK_ATTRIBUTE *tmpl,
1917034448feSmcpowers CK_ULONG tmpl_len, boolean_t create)
1918034448feSmcpowers {
1919034448feSmcpowers
1920034448feSmcpowers /* This check should never be true, if it is, it's a bug */
1921034448feSmcpowers if (object->isFreeObject < FREE_ALLOWED_KEY)
1922034448feSmcpowers return (B_FALSE);
1923034448feSmcpowers
1924034448feSmcpowers if (!create) {
1925034448feSmcpowers /* Turn off the Sensitive flag */
1926034448feSmcpowers if (object->isSensitive) {
1927d3a28a55Sdinak if (set_template_boolean(CKA_SENSITIVE, tmpl, tmpl_len,
1928d3a28a55Sdinak B_TRUE, &falsevalue) == -1)
1929034448feSmcpowers goto failure;
1930034448feSmcpowers
1931034448feSmcpowers object->isFreeObject = FREE_ENABLED;
1932034448feSmcpowers }
1933034448feSmcpowers
1934034448feSmcpowers /* Turn off the Private flag */
1935034448feSmcpowers if (object->isPrivate) {
1936d3a28a55Sdinak if (set_template_boolean(CKA_PRIVATE, tmpl, tmpl_len,
1937d3a28a55Sdinak B_TRUE, &falsevalue) == -1)
1938034448feSmcpowers goto failure;
1939034448feSmcpowers
1940034448feSmcpowers object->isFreeObject = FREE_ENABLED;
1941034448feSmcpowers }
1942034448feSmcpowers }
1943034448feSmcpowers
1944034448feSmcpowers if (object->isToken) {
1945034448feSmcpowers object->isToken = B_FALSE;
1946034448feSmcpowers object->isFreeToken = FREE_ENABLED;
1947034448feSmcpowers object->isFreeObject = FREE_ENABLED;
1948034448feSmcpowers } else
1949034448feSmcpowers object->isFreeToken = FREE_DISABLED;
1950034448feSmcpowers
1951034448feSmcpowers /*
1952034448feSmcpowers * If isFreeObject is not in the FREE_ENABLED state yet, it can be
1953034448feSmcpowers * turned off because the object doesn't not need to be a FreeObject.
1954034448feSmcpowers */
1955034448feSmcpowers if (object->isFreeObject == FREE_ALLOWED_KEY)
1956034448feSmcpowers object->isFreeObject = FREE_DISABLED;
1957034448feSmcpowers
1958034448feSmcpowers return (B_TRUE);
1959034448feSmcpowers
1960034448feSmcpowers failure:
1961034448feSmcpowers object->isFreeToken = FREE_DISABLED;
1962034448feSmcpowers object->isFreeObject = FREE_DISABLED;
1963034448feSmcpowers return (B_FALSE);
1964034448feSmcpowers }
1965034448feSmcpowers
1966034448feSmcpowers /*
1967034448feSmcpowers * This function sets the CKA_TOKEN flag on a given object template depending
1968034448feSmcpowers * if the slot being used is a keystore.
1969034448feSmcpowers *
1970034448feSmcpowers * If the object is a token, but the slot is not the system keystore or has
1971034448feSmcpowers * no keystore, then set the template to token = false; otherwise it's true.
1972034448feSmcpowers * In addition we know ahead of time what the value is, so if the value is
1973034448feSmcpowers * already correct, bypass the setting function
1974034448feSmcpowers */
1975034448feSmcpowers CK_RV
meta_freetoken_set(CK_ULONG slot_num,CK_BBOOL * current_value,CK_ATTRIBUTE * tmpl,CK_ULONG tmpl_len)1976034448feSmcpowers meta_freetoken_set(CK_ULONG slot_num, CK_BBOOL *current_value,
1977034448feSmcpowers CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len)
1978034448feSmcpowers {
1979034448feSmcpowers
1980034448feSmcpowers if (slot_num == get_keystore_slotnum()) {
1981034448feSmcpowers if (*current_value == TRUE)
1982034448feSmcpowers return (CKR_OK);
1983034448feSmcpowers
1984034448feSmcpowers if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE,
1985034448feSmcpowers &truevalue) == -1)
1986034448feSmcpowers return (CKR_FUNCTION_FAILED);
1987034448feSmcpowers
1988034448feSmcpowers } else {
1989034448feSmcpowers
1990034448feSmcpowers if (*current_value == FALSE)
1991034448feSmcpowers return (CKR_OK);
1992034448feSmcpowers
1993034448feSmcpowers if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE,
1994034448feSmcpowers &falsevalue) == -1)
1995034448feSmcpowers return (CKR_FUNCTION_FAILED);
1996034448feSmcpowers
1997034448feSmcpowers *current_value = FALSE;
1998034448feSmcpowers }
1999034448feSmcpowers
2000034448feSmcpowers return (CKR_OK);
2001034448feSmcpowers }
2002034448feSmcpowers
2003034448feSmcpowers /*
2004034448feSmcpowers * Cloning function for meta_freeobject_clone() to use. This function
2005034448feSmcpowers * is streamlined because we know what the object is and this should
2006034448feSmcpowers * not be called as a generic cloner.
2007034448feSmcpowers */
2008034448feSmcpowers
2009034448feSmcpowers static CK_RV
meta_freeobject_clone_maker(meta_session_t * session,meta_object_t * object,CK_ULONG slotnum)2010034448feSmcpowers meta_freeobject_clone_maker(meta_session_t *session, meta_object_t *object,
2011034448feSmcpowers CK_ULONG slotnum)
2012034448feSmcpowers {
2013034448feSmcpowers
2014034448feSmcpowers slot_object_t *slot_object = NULL;
2015034448feSmcpowers slot_session_t *slot_session = NULL;
2016034448feSmcpowers CK_RV rv;
2017034448feSmcpowers
2018034448feSmcpowers rv = meta_slot_object_alloc(&slot_object);
2019034448feSmcpowers if (rv != CKR_OK)
2020034448feSmcpowers goto cleanup;
2021034448feSmcpowers
2022034448feSmcpowers rv = meta_get_slot_session(slotnum, &slot_session,
2023034448feSmcpowers session->session_flags);
2024034448feSmcpowers if (rv != CKR_OK)
2025034448feSmcpowers goto cleanup;
2026034448feSmcpowers
2027034448feSmcpowers rv = clone_by_create(object, slot_object, slot_session);
2028034448feSmcpowers if (rv == CKR_OK) {
2029034448feSmcpowers object->clones[slotnum] = slot_object;
2030034448feSmcpowers meta_slot_object_activate(slot_object, slot_session, B_TRUE);
2031034448feSmcpowers }
2032034448feSmcpowers
2033034448feSmcpowers cleanup:
2034034448feSmcpowers meta_release_slot_session(slot_session);
2035034448feSmcpowers return (rv);
2036034448feSmcpowers
2037034448feSmcpowers }
2038034448feSmcpowers
2039034448feSmcpowers /*
2040034448feSmcpowers * This function is called when a object is a FreeObject.
2041034448feSmcpowers *
2042034448feSmcpowers * What we are given is an object that has been generated on a provider
2043034448feSmcpowers * that is not its final usage place. That maybe because:
2044034448feSmcpowers * 1) it's a token and needs to be stored in keystore.
2045034448feSmcpowers * 2) it was to be a private/sensitive object that we modified so we could know
2046034448feSmcpowers * the important attributes for cloning before we make it private/sensitive.
2047034448feSmcpowers */
2048034448feSmcpowers
2049034448feSmcpowers boolean_t
meta_freeobject_clone(meta_session_t * session,meta_object_t * object)2050034448feSmcpowers meta_freeobject_clone(meta_session_t *session, meta_object_t *object)
2051034448feSmcpowers {
2052034448feSmcpowers CK_RV rv;
2053034448feSmcpowers CK_ULONG keystore_slotnum;
2054034448feSmcpowers CK_ATTRIBUTE attr[2];
2055034448feSmcpowers boolean_t failover = B_FALSE;
2056034448feSmcpowers
2057034448feSmcpowers if (object->attributes == NULL) {
2058034448feSmcpowers rv = meta_object_copyin(object);
2059034448feSmcpowers if (rv != CKR_OK)
2060034448feSmcpowers return (rv);
2061034448feSmcpowers }
2062034448feSmcpowers
2063034448feSmcpowers if (object->isPrivate) {
2064034448feSmcpowers CK_OBJECT_HANDLE new_clone;
2065034448feSmcpowers CK_ULONG slotnum = object->master_clone_slotnum;
2066034448feSmcpowers slot_session_t *slot_session;
2067034448feSmcpowers
2068034448feSmcpowers attr[0].type = CKA_PRIVATE;
2069034448feSmcpowers attr[0].pValue = &truevalue;
2070034448feSmcpowers attr[0].ulValueLen = sizeof (truevalue);
2071034448feSmcpowers
2072034448feSmcpowers /* Set the master attribute list */
2073034448feSmcpowers rv = attribute_set_value(attr, object->attributes,
2074034448feSmcpowers object->num_attributes);
2075034448feSmcpowers if (rv > 0)
2076034448feSmcpowers return (CKR_FUNCTION_FAILED);
2077034448feSmcpowers
2078034448feSmcpowers /* Get a slot session */
2079034448feSmcpowers rv = meta_get_slot_session(slotnum, &slot_session,
2080034448feSmcpowers session->session_flags);
2081034448feSmcpowers if (rv > 0)
2082034448feSmcpowers return (rv);
2083034448feSmcpowers
2084034448feSmcpowers /* Create the new CKA_PRIVATE one */
2085034448feSmcpowers rv = FUNCLIST(slot_session->fw_st_id)->\
2086034448feSmcpowers C_CopyObject(slot_session->hSession,
2087034448feSmcpowers object->clones[slotnum]->hObject, attr, 1, &new_clone);
2088034448feSmcpowers
2089034448feSmcpowers if (rv == CKR_USER_NOT_LOGGED_IN) {
2090034448feSmcpowers /*
2091034448feSmcpowers * If the CopyObject fails, we may be using a provider
2092034448feSmcpowers * that has a keystore that is not the default
2093034448feSmcpowers * keystore set in metaslot or has object management
2094034448feSmcpowers * abilities. In which case we should write this
2095034448feSmcpowers * object to metaslot's keystore and let the failover.
2096034448feSmcpowers * rest of the function know we've changed providers.
2097034448feSmcpowers */
2098034448feSmcpowers failover = B_TRUE;
2099034448feSmcpowers keystore_slotnum = get_keystore_slotnum();
2100034448feSmcpowers if (object->clones[keystore_slotnum] == NULL) {
2101034448feSmcpowers rv = meta_freeobject_clone_maker(session,
2102034448feSmcpowers object, keystore_slotnum);
2103034448feSmcpowers if (rv != CKR_OK) {
2104034448feSmcpowers goto failure;
2105034448feSmcpowers }
2106034448feSmcpowers }
2107034448feSmcpowers object->master_clone_slotnum = keystore_slotnum;
2108034448feSmcpowers
2109034448feSmcpowers } else if (rv != CKR_OK) {
2110034448feSmcpowers meta_release_slot_session(slot_session);
2111034448feSmcpowers goto failure;
2112034448feSmcpowers }
2113034448feSmcpowers /* Remove the old object */
2114034448feSmcpowers rv = FUNCLIST(slot_session->fw_st_id)-> \
2115034448feSmcpowers C_DestroyObject(slot_session->hSession,
2116034448feSmcpowers object->clones[slotnum]->hObject);
2117034448feSmcpowers if (rv != CKR_OK) {
2118034448feSmcpowers meta_release_slot_session(slot_session);
2119034448feSmcpowers goto failure;
2120034448feSmcpowers }
2121034448feSmcpowers
2122034448feSmcpowers if (!failover)
2123034448feSmcpowers object->clones[slotnum]->hObject = new_clone;
2124034448feSmcpowers else
2125034448feSmcpowers object->clones[slotnum] = NULL;
2126034448feSmcpowers
2127034448feSmcpowers meta_release_slot_session(slot_session);
2128034448feSmcpowers
2129034448feSmcpowers }
2130034448feSmcpowers
2131034448feSmcpowers if (object->isSensitive) {
2132034448feSmcpowers slot_session_t *slot_session;
2133034448feSmcpowers CK_ULONG slotnum = object->master_clone_slotnum;
2134034448feSmcpowers
2135034448feSmcpowers attr[0].type = CKA_SENSITIVE;
2136034448feSmcpowers attr[0].pValue = &truevalue;
2137034448feSmcpowers attr[0].ulValueLen = sizeof (truevalue);
2138034448feSmcpowers rv = attribute_set_value(attr, object->attributes,
2139034448feSmcpowers object->num_attributes);
2140034448feSmcpowers if (rv != CKR_OK)
2141034448feSmcpowers goto failure;
2142034448feSmcpowers
2143034448feSmcpowers rv = meta_get_slot_session(slotnum, &slot_session,
2144034448feSmcpowers session->session_flags);
2145034448feSmcpowers if (rv == CKR_OK) {
2146034448feSmcpowers rv = FUNCLIST(slot_session->fw_st_id)-> \
2147034448feSmcpowers C_SetAttributeValue(slot_session->hSession,
2148034448feSmcpowers object->clones[slotnum]->hObject, attr, 1);
2149034448feSmcpowers
2150034448feSmcpowers meta_release_slot_session(slot_session);
2151034448feSmcpowers }
2152034448feSmcpowers }
2153034448feSmcpowers
2154034448feSmcpowers if (object->isFreeToken == FREE_ENABLED || failover) {
2155034448feSmcpowers keystore_slotnum = get_keystore_slotnum();
2156034448feSmcpowers if (object->clones[keystore_slotnum] == NULL) {
2157034448feSmcpowers rv = meta_freeobject_clone_maker(session, object,
2158034448feSmcpowers keystore_slotnum);
2159034448feSmcpowers if (rv != CKR_OK)
2160034448feSmcpowers goto failure;
2161034448feSmcpowers
2162034448feSmcpowers object->master_clone_slotnum = keystore_slotnum;
2163034448feSmcpowers }
2164034448feSmcpowers object->isFreeToken = FREE_ENABLED;
2165034448feSmcpowers }
2166034448feSmcpowers
2167034448feSmcpowers object->isFreeObject = FREE_ENABLED;
2168034448feSmcpowers return (CKR_OK);
2169034448feSmcpowers
2170034448feSmcpowers failure:
2171034448feSmcpowers object->isFreeToken = FREE_DISABLED;
2172034448feSmcpowers object->isFreeObject = FREE_DISABLED;
2173034448feSmcpowers return (rv);
2174034448feSmcpowers
2175034448feSmcpowers }
2176