1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 #include <stdlib.h> 28 #include <string.h> 29 #include <strings.h> 30 #include <errno.h> 31 #include <fcntl.h> 32 #include <sys/types.h> 33 #include <sys/stat.h> 34 #include "metaGlobal.h" 35 36 /* Size of the template for creating key used for wrap/unwrap */ 37 #define WRAP_KEY_TEMPLATE_SIZE 7 38 39 /* 40 * Information necessary to create keys for C_WrapKey/C_UnwrapKey 41 */ 42 typedef struct _wrap_info { 43 CK_OBJECT_CLASS class; /* class of the key for wrap/unwrap */ 44 CK_KEY_TYPE key_type; /* key type of key for wrap/unwrap */ 45 CK_ULONG key_length; /* length of key */ 46 CK_MECHANISM_TYPE mech_type; /* mech used for wrap/unwrap */ 47 CK_ULONG iv_length; /* length of iv for mech */ 48 49 boolean_t src_supports; 50 boolean_t dst_supports; 51 } wrap_info_t; 52 53 extern pthread_rwlock_t meta_sessionlist_lock; 54 extern meta_session_t *meta_sessionlist_head; 55 56 static wrap_info_t common_wrap_info[] = { 57 {CKO_SECRET_KEY, CKK_AES, 16, CKM_AES_CBC_PAD, 16, B_FALSE, B_FALSE}, 58 {CKO_SECRET_KEY, CKK_DES3, 24, CKM_DES3_CBC_PAD, 8, B_FALSE, B_FALSE}, 59 {CKO_SECRET_KEY, CKK_DES, 8, CKM_DES_CBC_PAD, 8, B_FALSE, B_FALSE}, 60 }; 61 62 static unsigned int num_common_wrap_info = 63 sizeof (common_wrap_info) / sizeof (wrap_info_t); 64 65 static wrap_info_t special_wrap_info[] = { 66 {CKO_SECRET_KEY, CKK_SKIPJACK, 12, CKM_SKIPJACK_WRAP, 0, 67 B_FALSE, B_FALSE}, 68 {CKO_SECRET_KEY, CKK_BATON, 40, CKM_BATON_WRAP, 0, 69 B_FALSE, B_FALSE}, 70 {CKO_SECRET_KEY, CKK_JUNIPER, 40, CKM_JUNIPER_WRAP, 0, 71 B_FALSE, B_FALSE}, 72 }; 73 static unsigned int num_special_wrap_info = 74 sizeof (special_wrap_info) / sizeof (wrap_info_t); 75 76 static wrap_info_t rsa_wrap_info[] = { 77 {CKO_PUBLIC_KEY, CKK_RSA, 0, CKM_RSA_PKCS, 0, 78 B_FALSE, B_FALSE}, 79 {CKO_PUBLIC_KEY, CKK_RSA, 0, CKM_RSA_X_509, 0, 80 B_FALSE, B_FALSE}, 81 }; 82 static unsigned int num_rsa_wrap_info = 83 sizeof (rsa_wrap_info) / sizeof (wrap_info_t); 84 85 86 static pthread_rwlock_t meta_objectclose_lock; 87 static pthread_rwlock_t tokenobject_list_lock; 88 static meta_object_t *tokenobject_list_head; 89 90 CK_BBOOL falsevalue = FALSE; 91 CK_BBOOL truevalue = TRUE; 92 93 /* 94 * Public and private exponent, and Module value for 95 * creating the RSA public/private key. 96 * 97 */ 98 static CK_BYTE PubExpo[3] = {0x01, 0x00, 0x01}; 99 CK_BYTE PriExpo[128] = { 100 0x8e, 0xc9, 0x70, 0x57, 0x6b, 0xcd, 0xfb, 0xa9, 101 0x19, 0xad, 0xcd, 0x91, 0x69, 0xd5, 0x52, 0xec, 102 0x72, 0x1e, 0x45, 0x15, 0x06, 0xdc, 0x65, 0x2d, 103 0x98, 0xc4, 0xce, 0x33, 0x54, 0x15, 0x70, 0x8d, 104 0xfa, 0x65, 0xea, 0x53, 0x44, 0xf3, 0x3e, 0x3f, 105 0xb4, 0x4c, 0x60, 0xd5, 0x01, 0x2d, 0xa4, 0x12, 106 0x99, 0xbf, 0x3f, 0x0b, 0xcd, 0xbb, 0x24, 0x10, 107 0x60, 0x30, 0x5e, 0x58, 0xf8, 0x59, 0xaa, 0xd1, 108 0x63, 0x3b, 0xbc, 0xcb, 0x94, 0x58, 0x38, 0x24, 109 0xfc, 0x65, 0x25, 0xc5, 0xa6, 0x51, 0xa2, 0x2e, 110 0xf1, 0x5e, 0xf5, 0xc1, 0xf5, 0x46, 0xf7, 0xbd, 111 0xc7, 0x62, 0xa8, 0xe2, 0x27, 0xd6, 0x94, 0x5b, 112 0xd3, 0xa2, 0xb5, 0x76, 0x42, 0x67, 0x6b, 0x86, 113 0x91, 0x97, 0x4d, 0x07, 0x92, 0x00, 0x4a, 0xdf, 114 0x0b, 0x65, 0x64, 0x05, 0x03, 0x48, 0x27, 0xeb, 115 0xce, 0x9a, 0x49, 0x7f, 0x3e, 0x10, 0xe0, 0x01}; 116 117 static CK_BYTE Modulus[128] = { 118 0x94, 0x32, 0xb9, 0x12, 0x1d, 0x68, 0x2c, 0xda, 119 0x2b, 0xe0, 0xe4, 0x97, 0x1b, 0x4d, 0xdc, 0x43, 120 0xdf, 0x38, 0x6e, 0x7b, 0x9f, 0x07, 0x58, 0xae, 121 0x9d, 0x82, 0x1e, 0xc7, 0xbc, 0x92, 0xbf, 0xd3, 122 0xce, 0x00, 0xbb, 0x91, 0xc9, 0x79, 0x06, 0x03, 123 0x1f, 0xbc, 0x9f, 0x94, 0x75, 0x29, 0x5f, 0xd7, 124 0xc5, 0xf3, 0x73, 0x8a, 0xa4, 0x35, 0x43, 0x7a, 125 0x00, 0x32, 0x97, 0x3e, 0x86, 0xef, 0x70, 0x6f, 126 0x18, 0x56, 0x15, 0xaa, 0x6a, 0x87, 0xe7, 0x8d, 127 0x7d, 0xdd, 0x1f, 0xa4, 0xe4, 0x31, 0xd4, 0x7a, 128 0x8c, 0x0e, 0x20, 0xd2, 0x23, 0xf5, 0x57, 0x3c, 129 0x1b, 0xa8, 0x44, 0xa4, 0x57, 0x8f, 0x33, 0x52, 130 0xad, 0x83, 0xae, 0x4a, 0x97, 0xa6, 0x1e, 0xa6, 131 0x2b, 0xfa, 0xea, 0xeb, 0x6e, 0x71, 0xb8, 0xb6, 132 0x0a, 0x36, 0xed, 0x83, 0xce, 0xb0, 0xdf, 0xc1, 133 0xd4, 0x3a, 0xe9, 0x99, 0x6f, 0xf3, 0x96, 0xb7}; 134 135 static CK_RV 136 meta_clone_template_setup(meta_object_t *object, 137 const generic_attr_t *attributes, size_t num_attributes); 138 139 /* 140 * meta_objectManager_initialize 141 * 142 * Called from meta_Initialize. Initializes all the variables used 143 * by the object manager. 144 */ 145 CK_RV 146 meta_objectManager_initialize() 147 { 148 if (pthread_rwlock_init(&meta_objectclose_lock, NULL) != 0) { 149 return (CKR_FUNCTION_FAILED); 150 } 151 152 if (pthread_rwlock_init(&tokenobject_list_lock, NULL) != 0) { 153 (void) pthread_rwlock_destroy(&meta_objectclose_lock); 154 return (CKR_FUNCTION_FAILED); 155 } 156 157 tokenobject_list_head = NULL; 158 159 return (CKR_OK); 160 } 161 162 void 163 meta_objectManager_finalize() 164 { 165 /* 166 * If there are still any token object in the list, need to 167 * deactivate all of them. 168 */ 169 (void) meta_token_object_deactivate(ALL_TOKEN); 170 171 (void) pthread_rwlock_destroy(&meta_objectclose_lock); 172 (void) pthread_rwlock_destroy(&tokenobject_list_lock); 173 } 174 175 176 177 /* 178 * meta_handle2object 179 * 180 * Convert a CK_OBJECT_HANDLE to the corresponding metaobject. If 181 * successful, a reader-lock on the object will be held to indicate 182 * that it's in use. Call OBJRELEASE() when finished. 183 * 184 */ 185 CK_RV 186 meta_handle2object(CK_OBJECT_HANDLE hObject, meta_object_t **object) 187 { 188 meta_object_t *tmp_object = (meta_object_t *)(hObject); 189 190 /* Check for bad args (eg CK_INVALID_HANDLE, which is 0/NULL). */ 191 if (tmp_object == NULL) { 192 *object = NULL; 193 return (CKR_OBJECT_HANDLE_INVALID); 194 } 195 196 197 /* Lock to ensure the magic-check + read-lock is atomic. */ 198 (void) pthread_rwlock_rdlock(&meta_objectclose_lock); 199 200 if (tmp_object->magic_marker != METASLOT_OBJECT_MAGIC) { 201 (void) pthread_rwlock_unlock(&meta_objectclose_lock); 202 *object = NULL; 203 return (CKR_OBJECT_HANDLE_INVALID); 204 } 205 (void) pthread_rwlock_rdlock(&tmp_object->object_lock); 206 (void) pthread_rwlock_unlock(&meta_objectclose_lock); 207 208 *object = tmp_object; 209 return (CKR_OK); 210 } 211 212 213 /* 214 * meta_object_alloc 215 * 216 * Creates a new metaobject, but does not yet add it to the object list. 217 * Once the caller has finished initializing the object (by setting 218 * object attributes), meta_object_add should be called. This two-step 219 * process prevents others from seeing the object until fully intitialized. 220 * 221 */ 222 CK_RV 223 meta_object_alloc(meta_session_t *session, meta_object_t **object) 224 { 225 meta_object_t *new_object; 226 CK_ULONG num_slots; 227 228 /* Allocate memory for the object. */ 229 new_object = calloc(1, sizeof (meta_object_t)); 230 if (new_object == NULL) 231 return (CKR_HOST_MEMORY); 232 233 num_slots = meta_slotManager_get_slotcount(); 234 235 new_object->clones = calloc(num_slots, sizeof (slot_object_t *)); 236 if (new_object->clones == NULL) { 237 free(new_object); 238 return (CKR_HOST_MEMORY); 239 } 240 241 new_object->tried_create_clone = calloc(num_slots, sizeof (boolean_t)); 242 if (new_object->tried_create_clone == NULL) { 243 free(new_object->clones); 244 free(new_object); 245 return (CKR_HOST_MEMORY); 246 } 247 248 /* Initialize the object fields. */ 249 new_object->magic_marker = METASLOT_OBJECT_MAGIC; 250 (void) pthread_rwlock_init(&new_object->object_lock, NULL); 251 (void) pthread_rwlock_init(&new_object->attribute_lock, NULL); 252 (void) pthread_mutex_init(&new_object->clone_create_lock, NULL); 253 (void) pthread_mutex_init(&new_object->isClosingObject_lock, NULL); 254 new_object->creator_session = session; 255 256 *object = new_object; 257 258 return (CKR_OK); 259 } 260 261 262 /* 263 * meta_object_get_attr 264 * 265 * Get attribute values to fill in attribute values 266 * being kept in the metaslot object. The following 4 attributes 267 * in the meta_object_t structure will be filled in: 268 * isToken, isPrivate, isSensitive, isExtractable 269 * 270 * It's basically an easy way to do a C_GetAttributeValue. 271 * So, the hSession argument is assumed 272 * to be valid, and the pointer to meta_object_t is also assumed 273 * to be valid. 274 */ 275 CK_RV 276 meta_object_get_attr(slot_session_t *slot_session, CK_OBJECT_HANDLE hObject, 277 meta_object_t *object) 278 { 279 CK_BBOOL is_sensitive = object->isSensitive; 280 CK_BBOOL is_extractable = object->isExtractable; 281 CK_BBOOL is_token = B_FALSE, is_private = B_FALSE; 282 CK_KEY_TYPE keytype; 283 CK_OBJECT_CLASS class; 284 CK_ATTRIBUTE attrs[3]; 285 CK_RV rv; 286 CK_SESSION_HANDLE hSession = slot_session->hSession; 287 CK_SLOT_ID fw_st_id = slot_session->fw_st_id; 288 int count = 1; 289 290 attrs[0].type = CKA_CLASS; 291 attrs[0].pValue = &class; 292 attrs[0].ulValueLen = sizeof (class); 293 294 if (object->isFreeObject != FREE_ENABLED) { 295 attrs[1].type = CKA_TOKEN; 296 attrs[1].pValue = &is_token; 297 attrs[1].ulValueLen = sizeof (is_token); 298 count++; 299 } 300 301 /* 302 * If this is a freeobject, we already know the Private value 303 * and we don't want to overwrite it with the wrong value 304 */ 305 if (object->isFreeObject <= FREE_DISABLED) { 306 attrs[count].type = CKA_PRIVATE; 307 attrs[count].pValue = &is_private; 308 attrs[count].ulValueLen = sizeof (is_private); 309 count++; 310 } else 311 is_private = object->isPrivate; 312 313 rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, hObject, 314 attrs, count); 315 if (rv != CKR_OK) { 316 return (rv); 317 } 318 319 count = 0; 320 switch (class) { 321 case CKO_PRIVATE_KEY: 322 case CKO_SECRET_KEY: 323 /* Only need to check these for private & secret keys */ 324 attrs[0].type = CKA_EXTRACTABLE; 325 attrs[0].pValue = &is_extractable; 326 attrs[0].ulValueLen = sizeof (is_extractable); 327 count = 1; 328 329 /* 330 * If this is a freeobject, we already know the Sensitive 331 * value and we don't want to overwrite it with the wrong 332 * value. 333 */ 334 335 if (object->isFreeObject <= FREE_DISABLED) { 336 attrs[1].type = CKA_SENSITIVE; 337 attrs[1].pValue = &is_sensitive; 338 attrs[1].ulValueLen = sizeof (is_sensitive); 339 count = 2; 340 341 /* 342 * We only need the key type if this is the first 343 * time we've looked at the object 344 */ 345 if (object->isFreeObject == FREE_UNCHECKED) { 346 attrs[2].type = CKA_KEY_TYPE; 347 attrs[2].pValue = &keytype; 348 attrs[2].ulValueLen = sizeof (keytype); 349 count = 3; 350 } 351 } 352 353 break; 354 355 case CKO_PUBLIC_KEY: 356 if (object->isFreeObject == FREE_UNCHECKED) { 357 attrs[count].type = CKA_KEY_TYPE; 358 attrs[count].pValue = &keytype; 359 attrs[count].ulValueLen = sizeof (keytype); 360 count++; 361 } 362 is_sensitive = CK_FALSE; 363 is_extractable = CK_TRUE; 364 break; 365 366 default: 367 object->isFreeObject = FREE_DISABLED; 368 is_sensitive = CK_FALSE; 369 is_extractable = CK_TRUE; 370 }; 371 372 if (count > 0) { 373 rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, hObject, 374 attrs, count); 375 if (rv != CKR_OK) { 376 return (rv); 377 } 378 379 if (object->isFreeObject == FREE_UNCHECKED) { 380 if (keytype == CKK_EC || keytype == CKK_RSA || 381 keytype == CKK_DH) { 382 if (metaslot_config.auto_key_migrate) { 383 object->isFreeObject = FREE_DISABLED; 384 object->isFreeToken = FREE_DISABLED; 385 } 386 387 object->isFreeObject = FREE_ENABLED; 388 if (is_token) 389 object->isFreeToken = FREE_ENABLED; 390 } else 391 object->isFreeObject = FREE_DISABLED; 392 393 } 394 395 } 396 397 object->isToken = is_token; 398 object->isPrivate = is_private; 399 object->isSensitive = is_sensitive; 400 object->isExtractable = is_extractable; 401 402 return (CKR_OK); 403 } 404 405 406 /* 407 * meta_object_activate 408 * 409 * Add a new metaobject to the list of objects. See also meta_object_create, 410 * which would be called to create an object before it is added. 411 */ 412 void 413 meta_object_activate(meta_object_t *new_object) 414 { 415 pthread_rwlock_t *list_lock; 416 meta_object_t **list_head; 417 418 /* 419 * For session objects, we keep the list in the session that created 420 * this object, because this object will be destroyed when that session 421 * is closed. 422 * 423 * For token objects, the list is global (ie, not associated with any 424 * particular session). 425 */ 426 if (new_object->isToken) { 427 list_lock = &tokenobject_list_lock; 428 list_head = &tokenobject_list_head; 429 } else { 430 list_lock = &new_object->creator_session->object_list_lock; 431 list_head = &new_object->creator_session->object_list_head; 432 } 433 434 /* Add object to the list of objects. */ 435 (void) pthread_rwlock_wrlock(list_lock); 436 INSERT_INTO_LIST(*list_head, new_object); 437 (void) pthread_rwlock_unlock(list_lock); 438 } 439 440 441 /* 442 * meta_object_deactivate 443 * 444 * Removes the object from the list of valid meta objects. Note 445 * that this function does not clean up any allocated 446 * resources (memory, object clones, etc). Cleaning up of 447 * allocated resources is done by calling the meta_object_dealloc() 448 * 449 */ 450 CK_RV 451 meta_object_deactivate(meta_object_t *object, boolean_t have_list_lock, 452 boolean_t have_object_lock) 453 { 454 pthread_rwlock_t *list_lock; 455 meta_object_t **list_head; 456 457 if (!have_object_lock) { 458 (void) pthread_rwlock_rdlock(&object->object_lock); 459 } 460 461 (void) pthread_mutex_lock(&object->isClosingObject_lock); 462 if (object->isClosingObject) { 463 /* Lost a delete race. */ 464 (void) pthread_mutex_unlock(&object->isClosingObject_lock); 465 OBJRELEASE(object); 466 return (CKR_OBJECT_HANDLE_INVALID); 467 } 468 object->isClosingObject = B_TRUE; 469 (void) pthread_mutex_unlock(&object->isClosingObject_lock); 470 471 if (object->isToken || (object->isFreeToken == FREE_ENABLED)) { 472 list_lock = &tokenobject_list_lock; 473 list_head = &tokenobject_list_head; 474 } else { 475 list_lock = &object->creator_session->object_list_lock; 476 list_head = &object->creator_session->object_list_head; 477 } 478 479 /* 480 * Remove object from the object list. Once removed, it will not 481 * be possible for another thread to begin using the object. 482 */ 483 (void) pthread_rwlock_wrlock(&meta_objectclose_lock); 484 if (!have_list_lock) { 485 (void) pthread_rwlock_wrlock(list_lock); 486 } 487 488 489 object->magic_marker = METASLOT_OBJECT_BADMAGIC; 490 /* 491 * Can't use the regular REMOVE_FROM_LIST() function because 492 * that will miss the "error cleanup" situation where object is not yet 493 * in the list (object->next == NULL && object->prev == NULL) 494 */ 495 if (*list_head == object) { 496 /* Object is the first one in the list */ 497 if (object->next) { 498 *list_head = object->next; 499 object->next->prev = NULL; 500 } else { 501 /* Object is the only one in the list */ 502 *list_head = NULL; 503 } 504 } else if (object->next != NULL || object->prev != NULL) { 505 if (object->next) { 506 object->prev->next = object->next; 507 object->next->prev = object->prev; 508 } else { 509 /* Object is the last one in the list */ 510 object->prev->next = NULL; 511 } 512 } 513 514 if (!have_list_lock) { 515 (void) pthread_rwlock_unlock(list_lock); 516 } 517 (void) pthread_rwlock_unlock(&meta_objectclose_lock); 518 519 /* 520 * Wait for anyone already using object to finish, by obtaining 521 * a writer-lock (need to release our reader-lock first). Once we 522 * get the write lock, we can just release it and finish cleaning 523 * up the object. 524 */ 525 (void) pthread_rwlock_unlock(&object->object_lock); /* rdlock */ 526 (void) pthread_rwlock_wrlock(&object->object_lock); 527 (void) pthread_rwlock_unlock(&object->object_lock); /* wrlock */ 528 529 530 return (CKR_OK); 531 } 532 533 534 /* 535 * meta_object_dealloc 536 * 537 * Performs final object cleanup, releasing any allocated memory and 538 * destroying any clones on other slots. Caller is assumed to have 539 * called meta_object_deactivate() before this function. 540 * 541 * Caller is assumed to have only reference to object, but should have 542 * released any lock. 543 * 544 * If "nukeSourceObj" argument is true, we will actually delete the 545 * object from the underlying slot. 546 */ 547 CK_RV 548 meta_object_dealloc(meta_session_t *session, meta_object_t *object, 549 boolean_t nukeSourceObj) 550 { 551 CK_RV rv, save_rv = CKR_OK; 552 CK_ULONG slotnum, num_slots; 553 CK_ULONG i; 554 555 /* First, delete all the clones of this object on other slots. */ 556 num_slots = meta_slotManager_get_slotcount(); 557 for (slotnum = 0; slotnum < num_slots; slotnum++) { 558 slot_session_t *obj_session; 559 slot_object_t *clone; 560 561 clone = object->clones[slotnum]; 562 if (clone == NULL) 563 continue; 564 if (nukeSourceObj || (!object->isToken && 565 !(object->isFreeToken == FREE_ENABLED && 566 get_keystore_slotnum() == slotnum))) { 567 568 rv = meta_get_slot_session(slotnum, &obj_session, 569 (session == NULL) ? 570 object->creator_session->session_flags : 571 session->session_flags); 572 573 if (rv == CKR_OK) { 574 rv = FUNCLIST(obj_session->fw_st_id)->\ 575 C_DestroyObject(obj_session->hSession, 576 clone->hObject); 577 578 meta_release_slot_session(obj_session); 579 if ((rv != CKR_OK) && (save_rv == CKR_OK)) { 580 save_rv = rv; 581 } 582 } 583 584 } 585 586 meta_slot_object_deactivate(clone); 587 meta_slot_object_dealloc(clone); 588 589 object->clones[slotnum] = NULL; 590 } 591 592 /* Now erase and delete any attributes in the metaobject. */ 593 dealloc_attributes(object->attributes, object->num_attributes); 594 595 free(object->clones); 596 free(object->tried_create_clone); 597 598 if (object->clone_template) { 599 for (i = 0; i < object->clone_template_size; i++) { 600 free(((object->clone_template)[i]).pValue); 601 } 602 free(object->clone_template); 603 } 604 605 /* Cleanup remaining object fields. */ 606 (void) pthread_rwlock_destroy(&object->object_lock); 607 (void) pthread_rwlock_destroy(&object->attribute_lock); 608 (void) pthread_mutex_destroy(&object->isClosingObject_lock); 609 (void) pthread_mutex_destroy(&object->clone_create_lock); 610 611 meta_object_delay_free(object); 612 613 return (save_rv); 614 } 615 616 617 /* 618 * meta_slot_object_alloc 619 */ 620 CK_RV 621 meta_slot_object_alloc(slot_object_t **object) { 622 slot_object_t *new_object; 623 624 new_object = calloc(1, sizeof (slot_object_t)); 625 if (new_object == NULL) 626 return (CKR_HOST_MEMORY); 627 628 *object = new_object; 629 return (CKR_OK); 630 } 631 632 633 /* 634 * meta_slot_object_activate 635 */ 636 void 637 meta_slot_object_activate(slot_object_t *object, 638 slot_session_t *creator_session, boolean_t isToken) 639 { 640 object->creator_session = creator_session; 641 642 if (isToken) { 643 extern slot_data_t *slots; 644 slot_data_t *slot; 645 646 slot = &(slots[object->creator_session->slotnum]); 647 648 (void) pthread_rwlock_wrlock(&slot->tokenobject_list_lock); 649 INSERT_INTO_LIST(slot->tokenobject_list_head, object); 650 (void) pthread_rwlock_unlock(&slot->tokenobject_list_lock); 651 } else { 652 slot_session_t *session = object->creator_session; 653 654 /* Add to session's list of session objects. */ 655 (void) pthread_rwlock_wrlock(&session->object_list_lock); 656 INSERT_INTO_LIST(session->object_list_head, object); 657 (void) pthread_rwlock_unlock(&session->object_list_lock); 658 } 659 660 /* 661 * This set tells the slot object that we are in the token list, 662 * but does not cause harm with the metaobject knowing the object 663 * isn't a token, but a freetoken 664 */ 665 666 object->isToken = isToken; 667 } 668 669 670 /* 671 * meta_slot_object_deactivate 672 * 673 * Remove the specified slot object from the appropriate object list. 674 */ 675 void 676 meta_slot_object_deactivate(slot_object_t *object) 677 { 678 slot_object_t **list_head; 679 pthread_rwlock_t *list_lock; 680 681 if (object->isToken) { 682 extern slot_data_t *slots; 683 slot_data_t *slot; 684 685 slot = &(slots[object->creator_session->slotnum]); 686 687 list_head = &slot->tokenobject_list_head; 688 list_lock = &slot->tokenobject_list_lock; 689 } else { 690 list_head = &object->creator_session->object_list_head; 691 list_lock = &object->creator_session->object_list_lock; 692 } 693 694 (void) pthread_rwlock_wrlock(list_lock); 695 REMOVE_FROM_LIST(*list_head, object); 696 (void) pthread_rwlock_unlock(list_lock); 697 } 698 699 700 /* 701 * meta_slot_object_dealloc 702 */ 703 void 704 meta_slot_object_dealloc(slot_object_t *object) 705 { 706 /* Not much cleanup for slot objects, unlike meta objects... */ 707 free(object); 708 } 709 710 711 /* 712 * meta_object_copyin 713 * 714 * When a key is generated/derived/unwrapped, the attribute values 715 * created by the token are not immediately read into our copy of the 716 * attributes. We defer this work until we actually need to know. 717 */ 718 CK_RV 719 meta_object_copyin(meta_object_t *object) 720 { 721 CK_RV rv = CKR_OK; 722 slot_session_t *session = NULL; 723 CK_ATTRIBUTE *attrs = NULL, *attrs_with_val = NULL; 724 slot_object_t *slot_object = NULL; 725 CK_ULONG num_attrs = 0, i, num_attrs_with_val; 726 CK_SESSION_HANDLE hSession; 727 CK_SLOT_ID fw_st_id; 728 729 /* Make sure no one else is looking at attributes. */ 730 (void) pthread_rwlock_wrlock(&object->attribute_lock); 731 732 /* Did we just lose a copyin race with another thread */ 733 if (object->attributes != NULL) { 734 goto finish; 735 } 736 737 slot_object = object->clones[object->master_clone_slotnum]; 738 739 rv = meta_get_slot_session(object->master_clone_slotnum, &session, 740 object->creator_session->session_flags); 741 if (rv != CKR_OK) { 742 goto finish; 743 } 744 745 /* 746 * first, get the master template of all the attributes 747 * for this object 748 */ 749 rv = get_master_attributes_by_object(session, slot_object, 750 &(object->attributes), &(object->num_attributes)); 751 if (rv != CKR_OK) { 752 goto finish; 753 } 754 755 /* 756 * Get value for each attribute items. 757 * 758 * Some attributes are required by the given object type. 759 * Some are optional. Get all the values first, and then 760 * make sure we have value for all required values, 761 */ 762 attrs = calloc(object->num_attributes, sizeof (CK_ATTRIBUTE)); 763 if (attrs == NULL) { 764 rv = CKR_HOST_MEMORY; 765 goto finish; 766 } 767 768 769 for (i = 0; i < object->num_attributes; i++) { 770 attrs[i].type = 771 ((object->attributes[i]).attribute).type; 772 } 773 num_attrs = object->num_attributes; 774 775 hSession = session->hSession; 776 fw_st_id = session->fw_st_id; 777 778 /* first, call C_GetAttributeValue() to get size for each attribute */ 779 rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, 780 slot_object->hObject, attrs, num_attrs); 781 /* 782 * If the return value is not CKR_OK, allow it to be 783 * CKR_ATTRIBUTE_TYPE_INVALID for now. 784 * Some attributes defined in PKCS#11 version 2.11 785 * might not be defined in earlier versions. We will 786 * TRY to work with those providers if the attribute 787 * is optional. 788 */ 789 if ((rv != CKR_OK) && (rv != CKR_ATTRIBUTE_TYPE_INVALID)) { 790 rv = CKR_FUNCTION_FAILED; /* make sure rv is appropriate */ 791 goto finish; 792 } 793 794 /* 795 * allocate space. 796 * Since we don't know how many attributes have 797 * values at this time, just assume all of them 798 * have values so we save one loop to count the number 799 * of attributes that have value. 800 */ 801 attrs_with_val = calloc(num_attrs, sizeof (CK_ATTRIBUTE)); 802 if (attrs_with_val == NULL) { 803 rv = CKR_HOST_MEMORY; 804 goto finish; 805 } 806 807 808 num_attrs_with_val = 0; 809 for (i = 0; i < num_attrs; i++) { 810 if (!(((CK_LONG)(attrs[i].ulValueLen)) > 0)) { 811 /* if it isn't an optional attr, len should be > 0 */ 812 if (!object->attributes[i].canBeEmptyValue) { 813 rv = CKR_FUNCTION_FAILED; 814 goto finish; 815 } 816 } else { 817 attrs_with_val[num_attrs_with_val].type = attrs[i].type; 818 attrs_with_val[num_attrs_with_val].ulValueLen = 819 attrs[i].ulValueLen; 820 attrs_with_val[num_attrs_with_val].pValue = 821 malloc(attrs[i].ulValueLen); 822 if (attrs_with_val[num_attrs_with_val].pValue == NULL) { 823 rv = CKR_HOST_MEMORY; 824 goto finish; 825 } 826 num_attrs_with_val++; 827 } 828 } 829 830 rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, 831 slot_object->hObject, attrs_with_val, num_attrs_with_val); 832 if (rv != CKR_OK) { 833 goto finish; 834 } 835 836 /* store these values into the meta object */ 837 for (i = 0; i < num_attrs_with_val; i++) { 838 rv = attribute_set_value(&(attrs_with_val[i]), 839 object->attributes, object->num_attributes); 840 if (rv != CKR_OK) { 841 goto finish; 842 } 843 } 844 845 finish: 846 (void) pthread_rwlock_unlock(&object->attribute_lock); 847 848 if (session) 849 meta_release_slot_session(session); 850 851 if (attrs) { 852 for (i = 0; i < num_attrs; i++) { 853 if (attrs[i].pValue != NULL) { 854 free(attrs[i].pValue); 855 } 856 } 857 free(attrs); 858 } 859 860 if (attrs_with_val) { 861 for (i = 0; i < num_attrs; i++) { 862 if (attrs_with_val[i].pValue != NULL) { 863 free(attrs_with_val[i].pValue); 864 } 865 } 866 free(attrs_with_val); 867 } 868 return (rv); 869 } 870 871 /* 872 * Create an object to be used for wrapping and unwrapping. 873 * The same template will be used for all wrapping/unwrapping keys all 874 * the time 875 */ 876 877 static CK_RV 878 create_wrap_unwrap_key(slot_session_t *slot_session, CK_OBJECT_HANDLE *hObject, 879 wrap_info_t *wrap_info, char *key_data, CK_ULONG key_len) 880 { 881 882 CK_OBJECT_CLASS objclass; 883 CK_KEY_TYPE keytype; 884 CK_RV rv = CKR_OK; 885 int i; 886 CK_ATTRIBUTE template[WRAP_KEY_TEMPLATE_SIZE]; 887 888 i = 0; 889 objclass = wrap_info->class; 890 template[i].type = CKA_CLASS; 891 template[i].pValue = &objclass; 892 template[i].ulValueLen = sizeof (objclass); 893 894 i++; 895 keytype = wrap_info->key_type; 896 template[i].type = CKA_KEY_TYPE; 897 template[i].pValue = &keytype; 898 template[i].ulValueLen = sizeof (keytype); 899 900 i++; 901 template[i].type = CKA_TOKEN; 902 template[i].pValue = &falsevalue; 903 template[i].ulValueLen = sizeof (falsevalue); 904 905 906 if (objclass == CKO_SECRET_KEY) { 907 i++; 908 template[i].type = CKA_VALUE; 909 template[i].pValue = key_data; 910 template[i].ulValueLen = key_len; 911 912 i++; 913 template[i].type = CKA_WRAP; 914 template[i].pValue = &truevalue; 915 template[i].ulValueLen = sizeof (truevalue); 916 917 i++; 918 template[i].type = CKA_UNWRAP; 919 template[i].pValue = &truevalue; 920 template[i].ulValueLen = sizeof (truevalue); 921 } else { 922 /* Modulus is the same for rsa public and private key */ 923 i++; 924 template[i].type = CKA_MODULUS; 925 template[i].pValue = Modulus; 926 template[i].ulValueLen = sizeof (Modulus); 927 928 if (objclass == CKO_PUBLIC_KEY) { 929 /* RSA public key */ 930 i++; 931 template[i].type = CKA_PUBLIC_EXPONENT; 932 template[i].pValue = PubExpo; 933 template[i].ulValueLen = sizeof (PubExpo); 934 935 i++; 936 template[i].type = CKA_WRAP; 937 template[i].pValue = &truevalue; 938 template[i].ulValueLen = sizeof (truevalue); 939 } else { 940 /* RSA private key */ 941 i++; 942 template[i].type = CKA_PRIVATE_EXPONENT; 943 template[i].pValue = PriExpo; 944 template[i].ulValueLen = sizeof (PriExpo); 945 946 i++; 947 template[i].type = CKA_UNWRAP; 948 template[i].pValue = &truevalue; 949 template[i].ulValueLen = sizeof (truevalue); 950 } 951 } 952 953 rv = FUNCLIST(slot_session->fw_st_id)->C_CreateObject( 954 slot_session->hSession, template, i + 1, hObject); 955 956 return (rv); 957 } 958 959 960 /* 961 * Create a clone of a non-sensitive and extractable object. 962 * If the template required for creating the clone doesn't exist, 963 * it will be retrieved from the master clone. 964 */ 965 static CK_RV 966 clone_by_create(meta_object_t *object, slot_object_t *new_clone, 967 slot_session_t *dst_slot_session) 968 { 969 CK_RV rv; 970 int free_token_index = -1; 971 972 if (object->attributes == NULL) { 973 rv = meta_object_copyin(object); 974 if (rv != CKR_OK) { 975 return (rv); 976 } 977 } 978 979 if (object->clone_template == NULL) { 980 rv = meta_clone_template_setup(object, object->attributes, 981 object->num_attributes); 982 if (rv != CKR_OK) { 983 return (rv); 984 } 985 } 986 987 if (object->isFreeToken == FREE_ENABLED) { 988 if (dst_slot_session->slotnum == get_keystore_slotnum()) 989 free_token_index = set_template_boolean(CKA_TOKEN, 990 object->clone_template, 991 object->clone_template_size, B_FALSE, &truevalue); 992 else 993 free_token_index = set_template_boolean(CKA_TOKEN, 994 object->clone_template, 995 object->clone_template_size, B_FALSE, &falsevalue); 996 } 997 998 /* Create the clone... */ 999 rv = FUNCLIST(dst_slot_session->fw_st_id)->C_CreateObject( 1000 dst_slot_session->hSession, object->clone_template, 1001 object->clone_template_size, &(new_clone->hObject)); 1002 1003 if (free_token_index != -1) { 1004 free_token_index = set_template_boolean(CKA_TOKEN, 1005 object->clone_template, object->clone_template_size, 1006 B_FALSE, &falsevalue); 1007 } 1008 1009 if (rv != CKR_OK) { 1010 return (rv); 1011 } 1012 1013 return (CKR_OK); 1014 } 1015 1016 /* 1017 * Goes through the list of wraping mechanisms, and returns the first 1018 * one that is supported by both the source and the destination slot. 1019 * If none of the mechanisms are supported by both slot, return the 1020 * first mechanism that's supported by the source slot 1021 */ 1022 static CK_RV 1023 find_best_match_wrap_mech(wrap_info_t *wrap_info, int num_info, 1024 CK_ULONG src_slotnum, CK_ULONG dst_slotnum, int *first_both_mech, 1025 int *first_src_mech) 1026 { 1027 1028 int i; 1029 boolean_t src_supports, dst_supports; 1030 CK_RV rv; 1031 CK_MECHANISM_INFO mech_info; 1032 1033 mech_info.flags = CKF_WRAP; 1034 1035 for (i = 0; i < num_info; i++) { 1036 src_supports = B_FALSE; 1037 dst_supports = B_FALSE; 1038 1039 rv = meta_mechManager_slot_supports_mech( 1040 (wrap_info[i]).mech_type, src_slotnum, 1041 &src_supports, NULL, B_FALSE, &mech_info); 1042 if (rv != CKR_OK) { 1043 return (rv); 1044 } 1045 1046 rv = meta_mechManager_slot_supports_mech( 1047 (wrap_info[i]).mech_type, dst_slotnum, 1048 &dst_supports, NULL, B_FALSE, &mech_info); 1049 if (rv != CKR_OK) { 1050 return (rv); 1051 } 1052 1053 /* both source and destination supports the mech */ 1054 if ((src_supports) && (dst_supports)) { 1055 *first_both_mech = i; 1056 return (CKR_OK); 1057 } 1058 1059 if ((src_supports) && (*first_src_mech == -1)) { 1060 *first_src_mech = i; 1061 } 1062 } 1063 return (CKR_OK); 1064 } 1065 1066 /* 1067 * Determine the wrapping/unwrapping mechanism to be used 1068 * 1069 * If possible, select a mechanism that's supported by both source 1070 * and destination slot. If none of the mechanisms are supported 1071 * by both slot, then, select the first one supported by 1072 * the source slot. 1073 */ 1074 1075 static CK_RV 1076 get_wrap_mechanism(CK_OBJECT_CLASS obj_class, CK_KEY_TYPE key_type, 1077 CK_ULONG src_slotnum, CK_ULONG dst_slotnum, wrap_info_t *wrap_info) 1078 { 1079 wrap_info_t *wrap_info_to_search = NULL; 1080 unsigned int num_wrap_info; 1081 CK_RV rv; 1082 int i; 1083 boolean_t src_supports = B_FALSE, dst_supports = B_FALSE; 1084 int first_src_mech, rsa_first_src_mech, first_both_mech; 1085 CK_MECHANISM_INFO mech_info; 1086 1087 mech_info.flags = CKF_WRAP; 1088 1089 if ((obj_class == CKO_PRIVATE_KEY) && (key_type == CKK_KEA)) { 1090 /* 1091 * only SKIPJACK keys can be used for wrapping 1092 * KEA private keys 1093 */ 1094 1095 for (i = 0; i < num_special_wrap_info; i++) { 1096 if ((special_wrap_info[i]).mech_type 1097 != CKM_SKIPJACK_WRAP) { 1098 continue; 1099 } 1100 1101 src_supports = B_FALSE; 1102 dst_supports = B_FALSE; 1103 1104 rv = meta_mechManager_slot_supports_mech( 1105 (special_wrap_info[i]).mech_type, src_slotnum, 1106 &src_supports, NULL, B_FALSE, &mech_info); 1107 if (rv != CKR_OK) { 1108 goto finish; 1109 } 1110 1111 rv = meta_mechManager_slot_supports_mech( 1112 (special_wrap_info[i]).mech_type, dst_slotnum, 1113 &dst_supports, NULL, B_FALSE, &mech_info); 1114 if (rv != CKR_OK) { 1115 goto finish; 1116 } 1117 1118 if (src_supports) { 1119 /* 1120 * both src and dst supports the mech or 1121 * only the src supports the mech 1122 */ 1123 (void) memcpy(wrap_info, 1124 &(special_wrap_info[i]), 1125 sizeof (wrap_info_t)); 1126 1127 wrap_info->src_supports = src_supports; 1128 wrap_info->dst_supports = dst_supports; 1129 rv = CKR_OK; 1130 goto finish; 1131 } 1132 1133 } 1134 1135 /* 1136 * if we are here, that means neither the source slot 1137 * nor the destination slots suppports CKM_SKIPJACK_WRAP 1138 */ 1139 rv = CKR_FUNCTION_FAILED; 1140 goto finish; 1141 } 1142 1143 if ((key_type == CKK_SKIPJACK) || (key_type == CKK_BATON) || 1144 (key_type == CKK_JUNIPER)) { 1145 /* special key types */ 1146 wrap_info_to_search = special_wrap_info; 1147 num_wrap_info = num_special_wrap_info; 1148 } else { 1149 /* use the regular wrapping mechanisms */ 1150 wrap_info_to_search = common_wrap_info; 1151 num_wrap_info = num_common_wrap_info; 1152 } 1153 1154 first_both_mech = -1; 1155 first_src_mech = -1; 1156 1157 rv = find_best_match_wrap_mech(wrap_info_to_search, num_wrap_info, 1158 src_slotnum, dst_slotnum, &first_both_mech, &first_src_mech); 1159 if (rv != CKR_OK) { 1160 goto finish; 1161 } 1162 1163 if (first_both_mech != -1) { 1164 (void) memcpy(wrap_info, 1165 &(wrap_info_to_search[first_both_mech]), 1166 sizeof (wrap_info_t)); 1167 1168 wrap_info->src_supports = B_TRUE; 1169 wrap_info->dst_supports = B_TRUE; 1170 rv = CKR_OK; 1171 goto finish; 1172 } 1173 1174 /* 1175 * If we are here, we did not find a mechanism that's supported 1176 * by both source and destination slot. 1177 * 1178 * If it is a secret key, can also try to wrap it with 1179 * a RSA public key 1180 */ 1181 if (obj_class == CKO_SECRET_KEY) { 1182 first_both_mech = -1; 1183 rsa_first_src_mech = -1; 1184 1185 rv = find_best_match_wrap_mech(rsa_wrap_info, 1186 num_rsa_wrap_info, src_slotnum, dst_slotnum, 1187 &first_both_mech, &rsa_first_src_mech); 1188 1189 if (rv != CKR_OK) { 1190 goto finish; 1191 } 1192 1193 if (first_both_mech > -1) { 1194 (void) memcpy(wrap_info, 1195 &(rsa_wrap_info[first_both_mech]), 1196 sizeof (wrap_info_t)); 1197 1198 wrap_info->src_supports = B_TRUE; 1199 wrap_info->dst_supports = B_TRUE; 1200 rv = CKR_OK; 1201 goto finish; 1202 } 1203 } 1204 1205 /* 1206 * if we are here, that means none of the mechanisms are supported 1207 * by both the source and the destination 1208 */ 1209 if (first_src_mech > -1) { 1210 /* source slot support one of the secret key mechs */ 1211 (void) memcpy(wrap_info, 1212 &(wrap_info_to_search[first_src_mech]), 1213 sizeof (wrap_info_t)); 1214 wrap_info->src_supports = B_TRUE; 1215 wrap_info->dst_supports = B_FALSE; 1216 rv = CKR_OK; 1217 } else if (rsa_first_src_mech > -1) { 1218 /* source slot support one of the RSA mechs */ 1219 (void) memcpy(wrap_info, &(rsa_wrap_info[rsa_first_src_mech]), 1220 sizeof (wrap_info_t)); 1221 1222 wrap_info->src_supports = B_TRUE; 1223 wrap_info->dst_supports = B_FALSE; 1224 rv = CKR_OK; 1225 } else { 1226 /* neither source nor destination support any wrap mechs */ 1227 rv = CKR_FUNCTION_FAILED; 1228 } 1229 1230 finish: 1231 return (rv); 1232 } 1233 1234 1235 /* 1236 * This is called if the object to be cloned is a sensitive object 1237 */ 1238 static CK_RV 1239 clone_by_wrap(meta_object_t *object, slot_object_t *new_clone, 1240 slot_session_t *dst_slot_session) 1241 { 1242 slot_session_t *src_slot_session = NULL; 1243 CK_OBJECT_HANDLE wrappingKey = NULL, unwrappingKey = NULL; 1244 CK_MECHANISM wrappingMech; 1245 CK_BYTE *wrappedKey = NULL; 1246 CK_ULONG wrappedKeyLen = 0; 1247 slot_object_t *slot_object = NULL; 1248 CK_RV rv = CKR_OK; 1249 CK_OBJECT_HANDLE unwrapped_obj; 1250 meta_object_t *tmp_meta_obj = NULL; 1251 slot_object_t *tmp_slot_obj = NULL; 1252 CK_OBJECT_CLASS obj_class; 1253 CK_KEY_TYPE key_type; 1254 meta_session_t *tmp_meta_session = NULL; 1255 CK_ATTRIBUTE unwrap_template[4]; 1256 char key_data[1024]; /* should be big enough for any key size */ 1257 char ivbuf[1024]; /* should be big enough for any mech */ 1258 wrap_info_t wrap_info; 1259 CK_ULONG key_len, unwrap_template_size; 1260 1261 slot_object = object->clones[object->master_clone_slotnum]; 1262 1263 rv = meta_get_slot_session(object->master_clone_slotnum, 1264 &src_slot_session, object->creator_session->session_flags); 1265 if (rv != CKR_OK) { 1266 return (rv); 1267 } 1268 1269 /* 1270 * get the object class and key type for unwrap template 1271 * This information will also be used for determining 1272 * which wrap mechanism and which key to use for 1273 * doing the wrapping 1274 */ 1275 unwrap_template[0].type = CKA_CLASS; 1276 unwrap_template[0].pValue = &obj_class; 1277 unwrap_template[0].ulValueLen = sizeof (obj_class); 1278 1279 unwrap_template[1].type = CKA_KEY_TYPE; 1280 unwrap_template[1].pValue = &key_type; 1281 unwrap_template[1].ulValueLen = sizeof (key_type); 1282 1283 rv = FUNCLIST(src_slot_session->fw_st_id)->C_GetAttributeValue( 1284 src_slot_session->hSession, slot_object->hObject, 1285 unwrap_template, 2); 1286 if (rv != CKR_OK) { 1287 goto finish; 1288 } 1289 1290 rv = get_wrap_mechanism(obj_class, key_type, src_slot_session->slotnum, 1291 dst_slot_session->slotnum, &wrap_info); 1292 if (rv != CKR_OK) { 1293 goto finish; 1294 } 1295 1296 /* 1297 * open the random device and read number of bytes required for 1298 * creating a secret key for wrapping and unwrapping 1299 */ 1300 if (wrap_info.class == CKO_SECRET_KEY) { 1301 1302 /* 1303 * /dev/urandom will be used for generating the key used 1304 * for doing the wrap/unwrap. It's should be ok to 1305 * use /dev/urandom because this key is used for this 1306 * one time operation only. It doesn't need to be stored. 1307 */ 1308 int fd; 1309 1310 while ((fd = open(RANDOM_DEVICE, O_RDONLY)) < 0) { 1311 if (errno != EINTR) 1312 break; 1313 } 1314 if (fd == -1) { 1315 rv = CKR_FUNCTION_FAILED; 1316 goto finish; 1317 } 1318 key_len = wrap_info.key_length; 1319 1320 if (looping_read(fd, key_data, key_len) != key_len) { 1321 rv = CKR_FUNCTION_FAILED; 1322 goto finish; 1323 } 1324 1325 if (wrap_info.iv_length > 0) { 1326 if (looping_read(fd, ivbuf, wrap_info.iv_length) 1327 != wrap_info.iv_length) { 1328 rv = CKR_FUNCTION_FAILED; 1329 goto finish; 1330 } 1331 } 1332 1333 (void) close(fd); 1334 } 1335 1336 /* create the wrapping key */ 1337 rv = create_wrap_unwrap_key(src_slot_session, &wrappingKey, 1338 &wrap_info, key_data, key_len); 1339 if (rv != CKR_OK) { 1340 goto finish; 1341 } 1342 1343 wrappingMech.mechanism = wrap_info.mech_type; 1344 wrappingMech.pParameter = ((wrap_info.iv_length > 0) ? ivbuf : NULL); 1345 wrappingMech.ulParameterLen = wrap_info.iv_length; 1346 1347 /* get the size of the wrapped key */ 1348 rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey( 1349 src_slot_session->hSession, &wrappingMech, 1350 wrappingKey, slot_object->hObject, NULL, &wrappedKeyLen); 1351 1352 if (rv != CKR_OK) { 1353 goto finish; 1354 } 1355 1356 wrappedKey = malloc(wrappedKeyLen * sizeof (CK_BYTE)); 1357 if (wrappedKey == NULL) { 1358 rv = CKR_HOST_MEMORY; 1359 goto finish; 1360 } 1361 1362 /* do the actual key wrapping */ 1363 rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey( 1364 src_slot_session->hSession, &wrappingMech, 1365 wrappingKey, slot_object->hObject, wrappedKey, &wrappedKeyLen); 1366 1367 if (rv != CKR_OK) { 1368 goto finish; 1369 } 1370 1371 /* explicitly force the unwrapped object to be not sensitive */ 1372 unwrap_template[2].type = CKA_SENSITIVE; 1373 unwrap_template[2].pValue = &falsevalue; 1374 unwrap_template[2].ulValueLen = sizeof (falsevalue); 1375 1376 unwrap_template[3].type = CKA_TOKEN; 1377 unwrap_template[3].pValue = &falsevalue; 1378 unwrap_template[3].ulValueLen = sizeof (falsevalue); 1379 1380 unwrap_template_size = 1381 sizeof (unwrap_template) / sizeof (CK_ATTRIBUTE); 1382 1383 if (!wrap_info.dst_supports) { 1384 /* 1385 * if we know for sure that the destination slot doesn't 1386 * support the wrapping mechanism, no point in trying. 1387 * go directly to unwrap in source slot, and create key 1388 * in destination 1389 */ 1390 goto unwrap_in_source; 1391 } 1392 1393 /* create the unwrapping key in destination slot */ 1394 if (wrap_info.key_type == CKK_RSA) { 1395 /* for RSA key, the unwrapping key need to be private key */ 1396 wrap_info.class = CKO_PRIVATE_KEY; 1397 } 1398 rv = create_wrap_unwrap_key(dst_slot_session, 1399 &unwrappingKey, &wrap_info, key_data, key_len); 1400 if (rv != CKR_OK) { 1401 goto finish; 1402 } 1403 1404 rv = FUNCLIST(dst_slot_session->fw_st_id)->C_UnwrapKey( 1405 dst_slot_session->hSession, &wrappingMech, 1406 unwrappingKey, wrappedKey, wrappedKeyLen, unwrap_template, 1407 unwrap_template_size, &(new_clone->hObject)); 1408 1409 if (rv != CKR_OK) { 1410 unwrap_in_source: 1411 1412 /* 1413 * There seemed to be a problem with unwrapping in the 1414 * destination slot. 1415 * Try to do the unwrap in the src slot so it becomes 1416 * a non-sensitive object, then, get all the attributes 1417 * and create the object in the destination slot 1418 */ 1419 1420 1421 if (wrap_info.class == CKO_SECRET_KEY) { 1422 /* unwrap with same key used for wrapping */ 1423 rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey( 1424 src_slot_session->hSession, 1425 &wrappingMech, wrappingKey, wrappedKey, 1426 wrappedKeyLen, unwrap_template, 1427 unwrap_template_size, &(unwrapped_obj)); 1428 } else { 1429 /* 1430 * If the object is wrapping with RSA public key, need 1431 * need to create RSA private key for unwrapping 1432 */ 1433 wrap_info.class = CKO_PRIVATE_KEY; 1434 rv = create_wrap_unwrap_key(src_slot_session, 1435 &unwrappingKey, &wrap_info, key_data, key_len); 1436 if (rv != CKR_OK) { 1437 goto finish; 1438 } 1439 rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey( 1440 src_slot_session->hSession, 1441 &wrappingMech, unwrappingKey, wrappedKey, 1442 wrappedKeyLen, unwrap_template, 1443 unwrap_template_size, &(unwrapped_obj)); 1444 } 1445 1446 1447 if (rv != CKR_OK) { 1448 goto finish; 1449 } 1450 1451 rv = meta_session_alloc(&tmp_meta_session); 1452 if (rv != CKR_OK) { 1453 goto finish; 1454 } 1455 1456 tmp_meta_session->session_flags = CKF_SERIAL_SESSION; 1457 1458 rv = meta_object_alloc(tmp_meta_session, &tmp_meta_obj); 1459 if (rv != CKR_OK) { 1460 goto finish; 1461 } 1462 1463 rv = meta_slot_object_alloc(&tmp_slot_obj); 1464 if (rv != CKR_OK) { 1465 goto finish; 1466 } 1467 1468 tmp_meta_obj->master_clone_slotnum = src_slot_session->slotnum; 1469 tmp_slot_obj->hObject = unwrapped_obj; 1470 tmp_meta_obj->clones[tmp_meta_obj->master_clone_slotnum] 1471 = tmp_slot_obj; 1472 meta_slot_object_activate(tmp_slot_obj, src_slot_session, 1473 B_FALSE); 1474 tmp_slot_obj = NULL; 1475 1476 rv = clone_by_create(tmp_meta_obj, new_clone, 1477 dst_slot_session); 1478 if (rv != CKR_OK) { 1479 goto finish; 1480 } 1481 } 1482 1483 finish: 1484 if (unwrappingKey) { 1485 (void) FUNCLIST(dst_slot_session->fw_st_id)->C_DestroyObject( 1486 dst_slot_session->hSession, unwrappingKey); 1487 } 1488 1489 if (wrappingKey) { 1490 (void) FUNCLIST(src_slot_session->fw_st_id)->C_DestroyObject( 1491 src_slot_session->hSession, wrappingKey); 1492 } 1493 1494 if (tmp_slot_obj) { 1495 (void) meta_slot_object_dealloc(tmp_slot_obj); 1496 } 1497 1498 if (tmp_meta_obj) { 1499 (void) meta_object_dealloc(tmp_meta_session, tmp_meta_obj, 1500 B_TRUE); 1501 } 1502 1503 if (tmp_meta_session) { 1504 (void) meta_session_dealloc(tmp_meta_session); 1505 } 1506 1507 if (wrappedKey) { 1508 free(wrappedKey); 1509 } 1510 1511 if (src_slot_session) { 1512 meta_release_slot_session(src_slot_session); 1513 } 1514 1515 return (rv); 1516 1517 } 1518 1519 1520 /* 1521 * meta_object_get_clone 1522 * 1523 * Creates a "clone" of a metaobject on the specified slot. A clone is a 1524 * copy of the object. 1525 * 1526 * Clones are cached, so that they can be reused with subsquent operations. 1527 */ 1528 CK_RV 1529 meta_object_get_clone(meta_object_t *object, 1530 CK_ULONG slot_num, slot_session_t *slot_session, 1531 slot_object_t **clone) 1532 { 1533 CK_RV rv = CKR_OK; 1534 slot_object_t *newclone = NULL; 1535 1536 /* Does a clone already exist? */ 1537 if (object->clones[slot_num] != NULL) { 1538 *clone = object->clones[slot_num]; 1539 return (CKR_OK); 1540 } 1541 1542 if ((object->isSensitive) && (object->isToken) && 1543 (!metaslot_auto_key_migrate)) { 1544 /* 1545 * if the object is a sensitive token object, and auto 1546 * key migrate is not allowed, will not create the clone 1547 * in another slot 1548 */ 1549 return (CKR_FUNCTION_FAILED); 1550 } 1551 1552 /* object attributes can't be extracted and attributes are not known */ 1553 if ((!object->isExtractable) && (object->attributes == NULL)) { 1554 return (CKR_FUNCTION_FAILED); 1555 } 1556 1557 (void) pthread_mutex_lock(&object->clone_create_lock); 1558 1559 /* Maybe someone just created one? */ 1560 if (object->clones[slot_num] != NULL) { 1561 *clone = object->clones[slot_num]; 1562 goto finish; 1563 } 1564 1565 /* 1566 * has an attempt already been made to create this object in 1567 * slot? If yes, and there's no clone, as indicated above, 1568 * that means this object can't be created in this slot. 1569 */ 1570 if (object->tried_create_clone[slot_num]) { 1571 (void) pthread_mutex_unlock(&object->clone_create_lock); 1572 return (CKR_FUNCTION_FAILED); 1573 } 1574 1575 rv = meta_slot_object_alloc(&newclone); 1576 if (rv != CKR_OK) 1577 goto finish; 1578 1579 object->tried_create_clone[slot_num] = B_TRUE; 1580 1581 /* 1582 * If this object is sensitive and we do not have not copied in the 1583 * attributes via FreeObject functionality, then we need to wrap it off 1584 * the provider. If we do have attributes, we can just create the 1585 * clone 1586 */ 1587 1588 if (object->isSensitive && object->attributes == NULL) { 1589 rv = clone_by_wrap(object, newclone, slot_session); 1590 } else { 1591 rv = clone_by_create(object, newclone, slot_session); 1592 } 1593 1594 if (rv != CKR_OK) { 1595 goto finish; 1596 } 1597 1598 object->clones[slot_num] = newclone; 1599 meta_slot_object_activate(newclone, slot_session, object->isToken); 1600 1601 *clone = newclone; 1602 newclone = NULL; 1603 finish: 1604 (void) pthread_mutex_unlock(&object->clone_create_lock); 1605 1606 if (newclone) 1607 meta_slot_object_dealloc(newclone); 1608 1609 return (rv); 1610 } 1611 1612 1613 /* 1614 * meta_setup_clone_template 1615 * 1616 * Create a clone template for the specified object. 1617 */ 1618 static CK_RV 1619 meta_clone_template_setup(meta_object_t *object, 1620 const generic_attr_t *attributes, size_t num_attributes) 1621 { 1622 CK_RV rv = CKR_OK; 1623 CK_ATTRIBUTE *clone_template; 1624 size_t i, c = 0; 1625 1626 clone_template = malloc(num_attributes * sizeof (CK_ATTRIBUTE)); 1627 if (clone_template == NULL) { 1628 rv = CKR_HOST_MEMORY; 1629 goto finish; 1630 } 1631 1632 /* Don't allow attributes to change while we look at them. */ 1633 (void) pthread_rwlock_rdlock(&object->attribute_lock); 1634 1635 for (i = 0; i < num_attributes; i++) { 1636 if (!attributes[i].isCloneAttr || 1637 (attributes[i].attribute.type == CKA_TOKEN && 1638 object->isFreeToken == FREE_DISABLED)) { 1639 continue; 1640 } 1641 if ((!(attributes[i].hasValueForClone)) && 1642 (attributes[i].canBeEmptyValue)) { 1643 continue; 1644 } 1645 1646 clone_template[c].type = attributes[i].attribute.type; 1647 clone_template[c].ulValueLen = 1648 attributes[i].attribute.ulValueLen; 1649 /* Allocate space to store the attribute value. */ 1650 clone_template[c].pValue = malloc(clone_template[c].ulValueLen); 1651 if (clone_template[c].pValue == NULL) { 1652 rv = CKR_HOST_MEMORY; 1653 (void) pthread_rwlock_unlock(&object->attribute_lock); 1654 goto finish; 1655 } 1656 1657 (void) memcpy(clone_template[c].pValue, 1658 object->attributes[i].attribute.pValue, 1659 clone_template[c].ulValueLen); 1660 c++; 1661 } 1662 1663 (void) pthread_rwlock_unlock(&object->attribute_lock); 1664 1665 object->clone_template = clone_template; 1666 object->clone_template_size = c; 1667 1668 finish: 1669 return (rv); 1670 } 1671 1672 1673 /* 1674 * meta_object_find_by_handle 1675 * 1676 * Search for an existing metaobject, using the object handle of a clone 1677 * on a particular slot. 1678 * 1679 * Returns a matching metaobject, or NULL if no match was found. 1680 */ 1681 meta_object_t * 1682 meta_object_find_by_handle(CK_OBJECT_HANDLE hObject, CK_ULONG slotnum, 1683 boolean_t token_only) 1684 { 1685 meta_object_t *object = NULL, *tmp_obj; 1686 meta_session_t *session; 1687 1688 if (!token_only) { 1689 (void) pthread_rwlock_rdlock(&meta_sessionlist_lock); 1690 session = meta_sessionlist_head; 1691 while (session != NULL) { 1692 /* lock the objects list while we look at it */ 1693 (void) pthread_rwlock_rdlock( 1694 &(session->object_list_lock)); 1695 tmp_obj = session->object_list_head; 1696 while (tmp_obj != NULL) { 1697 slot_object_t *slot_object; 1698 1699 (void) pthread_rwlock_rdlock( 1700 &(tmp_obj->object_lock)); 1701 slot_object = tmp_obj->clones[slotnum]; 1702 if (slot_object != NULL) { 1703 if (slot_object->hObject == hObject) { 1704 object = tmp_obj; 1705 } 1706 } 1707 (void) pthread_rwlock_unlock( 1708 &(tmp_obj->object_lock)); 1709 if (object != NULL) { 1710 break; 1711 } 1712 tmp_obj = tmp_obj->next; 1713 } 1714 (void) pthread_rwlock_unlock( 1715 &(session->object_list_lock)); 1716 if (object != NULL) { 1717 break; 1718 } 1719 session = session->next; 1720 } 1721 (void) pthread_rwlock_unlock(&meta_sessionlist_lock); 1722 } 1723 1724 if (object != NULL) { 1725 /* found the object, no need to look further */ 1726 return (object); 1727 } 1728 1729 /* 1730 * Look at list of token objects 1731 */ 1732 (void) pthread_rwlock_rdlock(&tokenobject_list_lock); 1733 tmp_obj = tokenobject_list_head; 1734 1735 while (tmp_obj != NULL) { 1736 slot_object_t *slot_object; 1737 1738 (void) pthread_rwlock_rdlock(&(tmp_obj->object_lock)); 1739 slot_object = tmp_obj->clones[slotnum]; 1740 if (slot_object != NULL) { 1741 if (slot_object->hObject == hObject) 1742 object = tmp_obj; 1743 } 1744 (void) pthread_rwlock_unlock(&(tmp_obj->object_lock)); 1745 if (object != NULL) { 1746 break; 1747 } 1748 tmp_obj = tmp_obj->next; 1749 } 1750 (void) pthread_rwlock_unlock(&tokenobject_list_lock); 1751 1752 return (object); 1753 } 1754 1755 CK_RV 1756 meta_token_object_deactivate(token_obj_type_t token_type) 1757 { 1758 meta_object_t *object, *tmp_object; 1759 CK_RV save_rv = CKR_OK, rv; 1760 1761 /* get a write lock on the token object list */ 1762 (void) pthread_rwlock_wrlock(&tokenobject_list_lock); 1763 1764 object = tokenobject_list_head; 1765 1766 /* go through each object and delete the one with matching type */ 1767 while (object != NULL) { 1768 tmp_object = object->next; 1769 1770 if ((token_type == ALL_TOKEN) || 1771 ((object->isPrivate) && (token_type == PRIVATE_TOKEN)) || 1772 ((!object->isPrivate) && (token_type == PUBLIC_TOKEN))) { 1773 rv = meta_object_deactivate(object, B_TRUE, B_FALSE); 1774 if ((rv != CKR_OK) && (save_rv == CKR_OK)) { 1775 save_rv = rv; 1776 goto finish; 1777 } 1778 rv = meta_object_dealloc(NULL, object, B_FALSE); 1779 if ((rv != CKR_OK) && (save_rv == CKR_OK)) { 1780 save_rv = rv; 1781 goto finish; 1782 } 1783 } 1784 object = tmp_object; 1785 } 1786 finish: 1787 (void) pthread_rwlock_unlock(&tokenobject_list_lock); 1788 return (save_rv); 1789 } 1790 1791 /* 1792 * This function adds the to-be-freed meta object to a linked list. 1793 * When the number of objects queued in the linked list reaches the 1794 * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first 1795 * object (FIFO) in the list. 1796 */ 1797 void 1798 meta_object_delay_free(meta_object_t *objp) 1799 { 1800 meta_object_t *tmp; 1801 1802 (void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex); 1803 1804 /* Add the newly deleted object at the end of the list */ 1805 objp->next = NULL; 1806 if (obj_delay_freed.first == NULL) { 1807 obj_delay_freed.last = objp; 1808 obj_delay_freed.first = objp; 1809 } else { 1810 obj_delay_freed.last->next = objp; 1811 obj_delay_freed.last = objp; 1812 } 1813 1814 if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) { 1815 /* 1816 * Free the first object in the list only if 1817 * the total count reaches maximum threshold. 1818 */ 1819 obj_delay_freed.count--; 1820 tmp = obj_delay_freed.first->next; 1821 free(obj_delay_freed.first); 1822 obj_delay_freed.first = tmp; 1823 } 1824 (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex); 1825 } 1826 1827 1828 /* 1829 * This function checks if the object passed can be a freeobject. 1830 * 1831 * If there is more than one provider that supports the supported freeobject 1832 * mechanisms then allow freeobjects to be an option. 1833 */ 1834 1835 boolean_t 1836 meta_freeobject_check(meta_session_t *session, meta_object_t *object, 1837 CK_MECHANISM *pMech, CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len, 1838 CK_KEY_TYPE keytype) 1839 { 1840 mech_support_info_t *info = &(session->mech_support_info); 1841 1842 /* 1843 * If key migration is turned off, or the object does not has any of 1844 * the required flags and there is only one slot, then we don't need 1845 * FreeObjects. 1846 */ 1847 if (!metaslot_auto_key_migrate || 1848 (!object->isToken && !object->isSensitive && 1849 meta_slotManager_get_slotcount() < 2)) 1850 goto failure; 1851 1852 /* 1853 * If this call is for key generation, check pMech for supported 1854 * FreeObject mechs 1855 */ 1856 if (pMech != NULL) { 1857 if (pMech->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN || 1858 pMech->mechanism == CKM_EC_KEY_PAIR_GEN || 1859 pMech->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN || 1860 pMech->mechanism == CKM_DH_PKCS_DERIVE) 1861 info->mech = pMech->mechanism; 1862 else 1863 goto failure; 1864 1865 /* 1866 * If this call is for an object creation, look inside the template 1867 * for supported FreeObject mechs 1868 */ 1869 } else if (tmpl_len > 0) { 1870 if (!get_template_ulong(CKA_KEY_TYPE, tmpl, tmpl_len, &keytype)) 1871 goto failure; 1872 1873 switch (keytype) { 1874 case CKK_RSA: 1875 info->mech = CKM_RSA_PKCS_KEY_PAIR_GEN; 1876 break; 1877 case CKK_EC: 1878 info->mech = CKM_EC_KEY_PAIR_GEN; 1879 break; 1880 case CKK_DH: 1881 info->mech = CKM_DH_PKCS_KEY_PAIR_GEN; 1882 break; 1883 default: 1884 goto failure; 1885 } 1886 } else 1887 goto failure; 1888 1889 /* Get the slot that support this mech... */ 1890 if (meta_mechManager_get_slots(info, B_FALSE, NULL) != CKR_OK) 1891 goto failure; 1892 1893 /* 1894 * If there is only one slot with the mech or the first slot in 1895 * the list is the keystore slot, we should bail. 1896 */ 1897 if (info->num_supporting_slots < 2 && 1898 info->supporting_slots[0]->slotnum == get_keystore_slotnum()) 1899 goto failure; 1900 1901 if (object->isToken) 1902 object->isFreeToken = FREE_ALLOWED_KEY; 1903 else 1904 object->isFreeToken = FREE_DISABLED; 1905 1906 object->isFreeObject = FREE_ALLOWED_KEY; 1907 1908 return (B_TRUE); 1909 1910 failure: 1911 object->isFreeToken = FREE_DISABLED; 1912 object->isFreeObject = FREE_DISABLED; 1913 return (B_FALSE); 1914 } 1915 1916 /* 1917 * This function assumes meta_freeobject_check() has just been called and set 1918 * the isFreeObject and/or isFreeToken vars to FREE_ALLOWED_KEY. 1919 * 1920 * If the template value for CKA_PRIVATE, CKA_SENSITIVE and/or CKA_TOKEN are 1921 * true, then isFreeObject is fully enabled. In addition isFreeToken is 1922 * enabled if is CKA_TOKEN true. 1923 * 1924 * If create is true, we are doing a C_CreateObject operation and don't 1925 * handle CKA_PRIVATE & CKA_SENSITIVE flags, we only care about CKA_TOKEN. 1926 */ 1927 1928 boolean_t 1929 meta_freeobject_set(meta_object_t *object, CK_ATTRIBUTE *tmpl, 1930 CK_ULONG tmpl_len, boolean_t create) 1931 { 1932 1933 /* This check should never be true, if it is, it's a bug */ 1934 if (object->isFreeObject < FREE_ALLOWED_KEY) 1935 return (B_FALSE); 1936 1937 if (!create) { 1938 /* Turn off the Sensitive flag */ 1939 if (object->isSensitive) { 1940 if (set_template_boolean(CKA_SENSITIVE, tmpl, tmpl_len, 1941 B_TRUE, &falsevalue) == -1) 1942 goto failure; 1943 1944 object->isFreeObject = FREE_ENABLED; 1945 } 1946 1947 /* Turn off the Private flag */ 1948 if (object->isPrivate) { 1949 if (set_template_boolean(CKA_PRIVATE, tmpl, tmpl_len, 1950 B_TRUE, &falsevalue) == -1) 1951 goto failure; 1952 1953 object->isFreeObject = FREE_ENABLED; 1954 } 1955 } 1956 1957 if (object->isToken) { 1958 object->isToken = B_FALSE; 1959 object->isFreeToken = FREE_ENABLED; 1960 object->isFreeObject = FREE_ENABLED; 1961 } else 1962 object->isFreeToken = FREE_DISABLED; 1963 1964 /* 1965 * If isFreeObject is not in the FREE_ENABLED state yet, it can be 1966 * turned off because the object doesn't not need to be a FreeObject. 1967 */ 1968 if (object->isFreeObject == FREE_ALLOWED_KEY) 1969 object->isFreeObject = FREE_DISABLED; 1970 1971 return (B_TRUE); 1972 1973 failure: 1974 object->isFreeToken = FREE_DISABLED; 1975 object->isFreeObject = FREE_DISABLED; 1976 return (B_FALSE); 1977 } 1978 1979 /* 1980 * This function sets the CKA_TOKEN flag on a given object template depending 1981 * if the slot being used is a keystore. 1982 * 1983 * If the object is a token, but the slot is not the system keystore or has 1984 * no keystore, then set the template to token = false; otherwise it's true. 1985 * In addition we know ahead of time what the value is, so if the value is 1986 * already correct, bypass the setting function 1987 */ 1988 CK_RV 1989 meta_freetoken_set(CK_ULONG slot_num, CK_BBOOL *current_value, 1990 CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len) 1991 { 1992 1993 if (slot_num == get_keystore_slotnum()) { 1994 if (*current_value == TRUE) 1995 return (CKR_OK); 1996 1997 if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE, 1998 &truevalue) == -1) 1999 return (CKR_FUNCTION_FAILED); 2000 2001 } else { 2002 2003 if (*current_value == FALSE) 2004 return (CKR_OK); 2005 2006 if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE, 2007 &falsevalue) == -1) 2008 return (CKR_FUNCTION_FAILED); 2009 2010 *current_value = FALSE; 2011 } 2012 2013 return (CKR_OK); 2014 } 2015 2016 /* 2017 * Cloning function for meta_freeobject_clone() to use. This function 2018 * is streamlined because we know what the object is and this should 2019 * not be called as a generic cloner. 2020 */ 2021 2022 static CK_RV 2023 meta_freeobject_clone_maker(meta_session_t *session, meta_object_t *object, 2024 CK_ULONG slotnum) 2025 { 2026 2027 slot_object_t *slot_object = NULL; 2028 slot_session_t *slot_session = NULL; 2029 CK_RV rv; 2030 2031 rv = meta_slot_object_alloc(&slot_object); 2032 if (rv != CKR_OK) 2033 goto cleanup; 2034 2035 rv = meta_get_slot_session(slotnum, &slot_session, 2036 session->session_flags); 2037 if (rv != CKR_OK) 2038 goto cleanup; 2039 2040 rv = clone_by_create(object, slot_object, slot_session); 2041 if (rv == CKR_OK) { 2042 object->clones[slotnum] = slot_object; 2043 meta_slot_object_activate(slot_object, slot_session, B_TRUE); 2044 } 2045 2046 cleanup: 2047 meta_release_slot_session(slot_session); 2048 return (rv); 2049 2050 } 2051 2052 /* 2053 * This function is called when a object is a FreeObject. 2054 * 2055 * What we are given is an object that has been generated on a provider 2056 * that is not its final usage place. That maybe because: 2057 * 1) it's a token and needs to be stored in keystore. 2058 * 2) it was to be a private/sensitive object that we modified so we could know 2059 * the important attributes for cloning before we make it private/sensitive. 2060 */ 2061 2062 boolean_t 2063 meta_freeobject_clone(meta_session_t *session, meta_object_t *object) 2064 { 2065 CK_RV rv; 2066 CK_ULONG keystore_slotnum; 2067 CK_ATTRIBUTE attr[2]; 2068 boolean_t failover = B_FALSE; 2069 2070 if (object->attributes == NULL) { 2071 rv = meta_object_copyin(object); 2072 if (rv != CKR_OK) 2073 return (rv); 2074 } 2075 2076 if (object->isPrivate) { 2077 CK_OBJECT_HANDLE new_clone; 2078 CK_ULONG slotnum = object->master_clone_slotnum; 2079 slot_session_t *slot_session; 2080 2081 attr[0].type = CKA_PRIVATE; 2082 attr[0].pValue = &truevalue; 2083 attr[0].ulValueLen = sizeof (truevalue); 2084 2085 /* Set the master attribute list */ 2086 rv = attribute_set_value(attr, object->attributes, 2087 object->num_attributes); 2088 if (rv > 0) 2089 return (CKR_FUNCTION_FAILED); 2090 2091 /* Get a slot session */ 2092 rv = meta_get_slot_session(slotnum, &slot_session, 2093 session->session_flags); 2094 if (rv > 0) 2095 return (rv); 2096 2097 /* Create the new CKA_PRIVATE one */ 2098 rv = FUNCLIST(slot_session->fw_st_id)->\ 2099 C_CopyObject(slot_session->hSession, 2100 object->clones[slotnum]->hObject, attr, 1, &new_clone); 2101 2102 if (rv == CKR_USER_NOT_LOGGED_IN) { 2103 /* 2104 * If the CopyObject fails, we may be using a provider 2105 * that has a keystore that is not the default 2106 * keystore set in metaslot or has object management 2107 * abilities. In which case we should write this 2108 * object to metaslot's keystore and let the failover. 2109 * rest of the function know we've changed providers. 2110 */ 2111 failover = B_TRUE; 2112 keystore_slotnum = get_keystore_slotnum(); 2113 if (object->clones[keystore_slotnum] == NULL) { 2114 rv = meta_freeobject_clone_maker(session, 2115 object, keystore_slotnum); 2116 if (rv != CKR_OK) { 2117 goto failure; 2118 } 2119 } 2120 object->master_clone_slotnum = keystore_slotnum; 2121 2122 } else if (rv != CKR_OK) { 2123 meta_release_slot_session(slot_session); 2124 goto failure; 2125 } 2126 /* Remove the old object */ 2127 rv = FUNCLIST(slot_session->fw_st_id)-> \ 2128 C_DestroyObject(slot_session->hSession, 2129 object->clones[slotnum]->hObject); 2130 if (rv != CKR_OK) { 2131 meta_release_slot_session(slot_session); 2132 goto failure; 2133 } 2134 2135 if (!failover) 2136 object->clones[slotnum]->hObject = new_clone; 2137 else 2138 object->clones[slotnum] = NULL; 2139 2140 meta_release_slot_session(slot_session); 2141 2142 } 2143 2144 if (object->isSensitive) { 2145 slot_session_t *slot_session; 2146 CK_ULONG slotnum = object->master_clone_slotnum; 2147 2148 attr[0].type = CKA_SENSITIVE; 2149 attr[0].pValue = &truevalue; 2150 attr[0].ulValueLen = sizeof (truevalue); 2151 rv = attribute_set_value(attr, object->attributes, 2152 object->num_attributes); 2153 if (rv != CKR_OK) 2154 goto failure; 2155 2156 rv = meta_get_slot_session(slotnum, &slot_session, 2157 session->session_flags); 2158 if (rv == CKR_OK) { 2159 rv = FUNCLIST(slot_session->fw_st_id)-> \ 2160 C_SetAttributeValue(slot_session->hSession, 2161 object->clones[slotnum]->hObject, attr, 1); 2162 2163 meta_release_slot_session(slot_session); 2164 } 2165 } 2166 2167 if (object->isFreeToken == FREE_ENABLED || failover) { 2168 keystore_slotnum = get_keystore_slotnum(); 2169 if (object->clones[keystore_slotnum] == NULL) { 2170 rv = meta_freeobject_clone_maker(session, object, 2171 keystore_slotnum); 2172 if (rv != CKR_OK) 2173 goto failure; 2174 2175 object->master_clone_slotnum = keystore_slotnum; 2176 } 2177 object->isFreeToken = FREE_ENABLED; 2178 } 2179 2180 object->isFreeObject = FREE_ENABLED; 2181 return (CKR_OK); 2182 2183 failure: 2184 object->isFreeToken = FREE_DISABLED; 2185 object->isFreeObject = FREE_DISABLED; 2186 return (rv); 2187 2188 } 2189