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