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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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