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(CKA_TOKEN, 1003 object->clone_template, object->clone_template_size, 1004 B_FALSE, &falsevalue); 1005 } 1006 1007 if (rv != CKR_OK) { 1008 return (rv); 1009 } 1010 1011 return (CKR_OK); 1012 } 1013 1014 /* 1015 * Goes through the list of wraping mechanisms, and returns the first 1016 * one that is supported by both the source and the destination slot. 1017 * If none of the mechanisms are supported by both slot, return the 1018 * first mechanism that's supported by the source slot 1019 */ 1020 static CK_RV 1021 find_best_match_wrap_mech(wrap_info_t *wrap_info, int num_info, 1022 CK_ULONG src_slotnum, CK_ULONG dst_slotnum, int *first_both_mech, 1023 int *first_src_mech) 1024 { 1025 1026 int i; 1027 boolean_t src_supports, dst_supports; 1028 CK_RV rv; 1029 CK_MECHANISM_INFO mech_info; 1030 1031 mech_info.flags = CKF_WRAP; 1032 1033 for (i = 0; i < num_info; i++) { 1034 src_supports = B_FALSE; 1035 dst_supports = B_FALSE; 1036 1037 rv = meta_mechManager_slot_supports_mech( 1038 (wrap_info[i]).mech_type, src_slotnum, 1039 &src_supports, NULL, B_FALSE, &mech_info); 1040 if (rv != CKR_OK) { 1041 return (rv); 1042 } 1043 1044 rv = meta_mechManager_slot_supports_mech( 1045 (wrap_info[i]).mech_type, dst_slotnum, 1046 &dst_supports, NULL, B_FALSE, &mech_info); 1047 if (rv != CKR_OK) { 1048 return (rv); 1049 } 1050 1051 /* both source and destination supports the mech */ 1052 if ((src_supports) && (dst_supports)) { 1053 *first_both_mech = i; 1054 return (CKR_OK); 1055 } 1056 1057 if ((src_supports) && (*first_src_mech == -1)) { 1058 *first_src_mech = i; 1059 } 1060 } 1061 return (CKR_OK); 1062 } 1063 1064 /* 1065 * Determine the wrapping/unwrapping mechanism to be used 1066 * 1067 * If possible, select a mechanism that's supported by both source 1068 * and destination slot. If none of the mechanisms are supported 1069 * by both slot, then, select the first one supported by 1070 * the source slot. 1071 */ 1072 1073 static CK_RV 1074 get_wrap_mechanism(CK_OBJECT_CLASS obj_class, CK_KEY_TYPE key_type, 1075 CK_ULONG src_slotnum, CK_ULONG dst_slotnum, wrap_info_t *wrap_info) 1076 { 1077 wrap_info_t *wrap_info_to_search = NULL; 1078 unsigned int num_wrap_info; 1079 CK_RV rv; 1080 int i; 1081 boolean_t src_supports = B_FALSE, dst_supports = B_FALSE; 1082 int first_src_mech, rsa_first_src_mech, first_both_mech; 1083 CK_MECHANISM_INFO mech_info; 1084 1085 mech_info.flags = CKF_WRAP; 1086 1087 if ((obj_class == CKO_PRIVATE_KEY) && (key_type == CKK_KEA)) { 1088 /* 1089 * only SKIPJACK keys can be used for wrapping 1090 * KEA private keys 1091 */ 1092 1093 for (i = 0; i < num_special_wrap_info; i++) { 1094 if ((special_wrap_info[i]).mech_type 1095 != CKM_SKIPJACK_WRAP) { 1096 continue; 1097 } 1098 1099 src_supports = B_FALSE; 1100 dst_supports = B_FALSE; 1101 1102 rv = meta_mechManager_slot_supports_mech( 1103 (special_wrap_info[i]).mech_type, src_slotnum, 1104 &src_supports, NULL, B_FALSE, &mech_info); 1105 if (rv != CKR_OK) { 1106 goto finish; 1107 } 1108 1109 rv = meta_mechManager_slot_supports_mech( 1110 (special_wrap_info[i]).mech_type, dst_slotnum, 1111 &dst_supports, NULL, B_FALSE, &mech_info); 1112 if (rv != CKR_OK) { 1113 goto finish; 1114 } 1115 1116 if (src_supports) { 1117 /* 1118 * both src and dst supports the mech or 1119 * only the src supports the mech 1120 */ 1121 (void) memcpy(wrap_info, 1122 &(special_wrap_info[i]), 1123 sizeof (wrap_info_t)); 1124 1125 wrap_info->src_supports = src_supports; 1126 wrap_info->dst_supports = dst_supports; 1127 rv = CKR_OK; 1128 goto finish; 1129 } 1130 1131 } 1132 1133 /* 1134 * if we are here, that means neither the source slot 1135 * nor the destination slots suppports CKM_SKIPJACK_WRAP 1136 */ 1137 rv = CKR_FUNCTION_FAILED; 1138 goto finish; 1139 } 1140 1141 if ((key_type == CKK_SKIPJACK) || (key_type == CKK_BATON) || 1142 (key_type == CKK_JUNIPER)) { 1143 /* special key types */ 1144 wrap_info_to_search = special_wrap_info; 1145 num_wrap_info = num_special_wrap_info; 1146 } else { 1147 /* use the regular wrapping mechanisms */ 1148 wrap_info_to_search = common_wrap_info; 1149 num_wrap_info = num_common_wrap_info; 1150 } 1151 1152 first_both_mech = -1; 1153 first_src_mech = -1; 1154 1155 rv = find_best_match_wrap_mech(wrap_info_to_search, num_wrap_info, 1156 src_slotnum, dst_slotnum, &first_both_mech, &first_src_mech); 1157 if (rv != CKR_OK) { 1158 goto finish; 1159 } 1160 1161 if (first_both_mech != -1) { 1162 (void) memcpy(wrap_info, 1163 &(wrap_info_to_search[first_both_mech]), 1164 sizeof (wrap_info_t)); 1165 1166 wrap_info->src_supports = B_TRUE; 1167 wrap_info->dst_supports = B_TRUE; 1168 rv = CKR_OK; 1169 goto finish; 1170 } 1171 1172 /* 1173 * If we are here, we did not find a mechanism that's supported 1174 * by both source and destination slot. 1175 * 1176 * If it is a secret key, can also try to wrap it with 1177 * a RSA public key 1178 */ 1179 if (obj_class == CKO_SECRET_KEY) { 1180 first_both_mech = -1; 1181 rsa_first_src_mech = -1; 1182 1183 rv = find_best_match_wrap_mech(rsa_wrap_info, 1184 num_rsa_wrap_info, src_slotnum, dst_slotnum, 1185 &first_both_mech, &rsa_first_src_mech); 1186 1187 if (rv != CKR_OK) { 1188 goto finish; 1189 } 1190 1191 if (first_both_mech > -1) { 1192 (void) memcpy(wrap_info, 1193 &(rsa_wrap_info[first_both_mech]), 1194 sizeof (wrap_info_t)); 1195 1196 wrap_info->src_supports = B_TRUE; 1197 wrap_info->dst_supports = B_TRUE; 1198 rv = CKR_OK; 1199 goto finish; 1200 } 1201 } 1202 1203 /* 1204 * if we are here, that means none of the mechanisms are supported 1205 * by both the source and the destination 1206 */ 1207 if (first_src_mech > -1) { 1208 /* source slot support one of the secret key mechs */ 1209 (void) memcpy(wrap_info, 1210 &(wrap_info_to_search[first_src_mech]), 1211 sizeof (wrap_info_t)); 1212 wrap_info->src_supports = B_TRUE; 1213 wrap_info->dst_supports = B_FALSE; 1214 rv = CKR_OK; 1215 } else if (rsa_first_src_mech > -1) { 1216 /* source slot support one of the RSA mechs */ 1217 (void) memcpy(wrap_info, &(rsa_wrap_info[rsa_first_src_mech]), 1218 sizeof (wrap_info_t)); 1219 1220 wrap_info->src_supports = B_TRUE; 1221 wrap_info->dst_supports = B_FALSE; 1222 rv = CKR_OK; 1223 } else { 1224 /* neither source nor destination support any wrap mechs */ 1225 rv = CKR_FUNCTION_FAILED; 1226 } 1227 1228 finish: 1229 return (rv); 1230 } 1231 1232 1233 /* 1234 * This is called if the object to be cloned is a sensitive object 1235 */ 1236 static CK_RV 1237 clone_by_wrap(meta_object_t *object, slot_object_t *new_clone, 1238 slot_session_t *dst_slot_session) 1239 { 1240 slot_session_t *src_slot_session = NULL; 1241 CK_OBJECT_HANDLE wrappingKey = NULL, unwrappingKey = NULL; 1242 CK_MECHANISM wrappingMech; 1243 CK_BYTE *wrappedKey = NULL; 1244 CK_ULONG wrappedKeyLen = 0; 1245 slot_object_t *slot_object = NULL; 1246 CK_RV rv = CKR_OK; 1247 CK_OBJECT_HANDLE unwrapped_obj; 1248 meta_object_t *tmp_meta_obj = NULL; 1249 slot_object_t *tmp_slot_obj = NULL; 1250 CK_OBJECT_CLASS obj_class; 1251 CK_KEY_TYPE key_type; 1252 meta_session_t *tmp_meta_session = NULL; 1253 CK_ATTRIBUTE unwrap_template[4]; 1254 char key_data[1024]; /* should be big enough for any key size */ 1255 char ivbuf[1024]; /* should be big enough for any mech */ 1256 wrap_info_t wrap_info; 1257 CK_ULONG key_len, unwrap_template_size; 1258 1259 slot_object = object->clones[object->master_clone_slotnum]; 1260 1261 rv = meta_get_slot_session(object->master_clone_slotnum, 1262 &src_slot_session, object->creator_session->session_flags); 1263 if (rv != CKR_OK) { 1264 return (rv); 1265 } 1266 1267 /* 1268 * get the object class and key type for unwrap template 1269 * This information will also be used for determining 1270 * which wrap mechanism and which key to use for 1271 * doing the wrapping 1272 */ 1273 unwrap_template[0].type = CKA_CLASS; 1274 unwrap_template[0].pValue = &obj_class; 1275 unwrap_template[0].ulValueLen = sizeof (obj_class); 1276 1277 unwrap_template[1].type = CKA_KEY_TYPE; 1278 unwrap_template[1].pValue = &key_type; 1279 unwrap_template[1].ulValueLen = sizeof (key_type); 1280 1281 rv = FUNCLIST(src_slot_session->fw_st_id)->C_GetAttributeValue( 1282 src_slot_session->hSession, slot_object->hObject, 1283 unwrap_template, 2); 1284 if (rv != CKR_OK) { 1285 goto finish; 1286 } 1287 1288 rv = get_wrap_mechanism(obj_class, key_type, src_slot_session->slotnum, 1289 dst_slot_session->slotnum, &wrap_info); 1290 if (rv != CKR_OK) { 1291 goto finish; 1292 } 1293 1294 /* 1295 * open the random device and read number of bytes required for 1296 * creating a secret key for wrapping and unwrapping 1297 */ 1298 if (wrap_info.class == CKO_SECRET_KEY) { 1299 1300 /* 1301 * /dev/urandom will be used for generating the key used 1302 * for doing the wrap/unwrap. It's should be ok to 1303 * use /dev/urandom because this key is used for this 1304 * one time operation only. It doesn't need to be stored. 1305 */ 1306 int fd; 1307 1308 while ((fd = open(RANDOM_DEVICE, O_RDONLY)) < 0) { 1309 if (errno != EINTR) 1310 break; 1311 } 1312 if (fd == -1) { 1313 rv = CKR_FUNCTION_FAILED; 1314 goto finish; 1315 } 1316 key_len = wrap_info.key_length; 1317 1318 if (looping_read(fd, key_data, key_len) != key_len) { 1319 rv = CKR_FUNCTION_FAILED; 1320 goto finish; 1321 } 1322 1323 if (wrap_info.iv_length > 0) { 1324 if (looping_read(fd, ivbuf, wrap_info.iv_length) 1325 != wrap_info.iv_length) { 1326 rv = CKR_FUNCTION_FAILED; 1327 goto finish; 1328 } 1329 } 1330 1331 (void) close(fd); 1332 } 1333 1334 /* create the wrapping key */ 1335 rv = create_wrap_unwrap_key(src_slot_session, &wrappingKey, 1336 &wrap_info, key_data, key_len); 1337 if (rv != CKR_OK) { 1338 goto finish; 1339 } 1340 1341 wrappingMech.mechanism = wrap_info.mech_type; 1342 wrappingMech.pParameter = ((wrap_info.iv_length > 0) ? ivbuf : NULL); 1343 wrappingMech.ulParameterLen = wrap_info.iv_length; 1344 1345 /* get the size of the wrapped key */ 1346 rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey( 1347 src_slot_session->hSession, &wrappingMech, 1348 wrappingKey, slot_object->hObject, NULL, &wrappedKeyLen); 1349 1350 if (rv != CKR_OK) { 1351 goto finish; 1352 } 1353 1354 wrappedKey = malloc(wrappedKeyLen * sizeof (CK_BYTE)); 1355 if (wrappedKey == NULL) { 1356 rv = CKR_HOST_MEMORY; 1357 goto finish; 1358 } 1359 1360 /* do the actual key wrapping */ 1361 rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey( 1362 src_slot_session->hSession, &wrappingMech, 1363 wrappingKey, slot_object->hObject, wrappedKey, &wrappedKeyLen); 1364 1365 if (rv != CKR_OK) { 1366 goto finish; 1367 } 1368 1369 /* explicitly force the unwrapped object to be not sensitive */ 1370 unwrap_template[2].type = CKA_SENSITIVE; 1371 unwrap_template[2].pValue = &falsevalue; 1372 unwrap_template[2].ulValueLen = sizeof (falsevalue); 1373 1374 unwrap_template[3].type = CKA_TOKEN; 1375 unwrap_template[3].pValue = &falsevalue; 1376 unwrap_template[3].ulValueLen = sizeof (falsevalue); 1377 1378 unwrap_template_size = 1379 sizeof (unwrap_template) / sizeof (CK_ATTRIBUTE); 1380 1381 if (!wrap_info.dst_supports) { 1382 /* 1383 * if we know for sure that the destination slot doesn't 1384 * support the wrapping mechanism, no point in trying. 1385 * go directly to unwrap in source slot, and create key 1386 * in destination 1387 */ 1388 goto unwrap_in_source; 1389 } 1390 1391 /* create the unwrapping key in destination slot */ 1392 if (wrap_info.key_type == CKK_RSA) { 1393 /* for RSA key, the unwrapping key need to be private key */ 1394 wrap_info.class = CKO_PRIVATE_KEY; 1395 } 1396 rv = create_wrap_unwrap_key(dst_slot_session, 1397 &unwrappingKey, &wrap_info, key_data, key_len); 1398 if (rv != CKR_OK) { 1399 goto finish; 1400 } 1401 1402 rv = FUNCLIST(dst_slot_session->fw_st_id)->C_UnwrapKey( 1403 dst_slot_session->hSession, &wrappingMech, 1404 unwrappingKey, wrappedKey, wrappedKeyLen, unwrap_template, 1405 unwrap_template_size, &(new_clone->hObject)); 1406 1407 if (rv != CKR_OK) { 1408 unwrap_in_source: 1409 1410 /* 1411 * There seemed to be a problem with unwrapping in the 1412 * destination slot. 1413 * Try to do the unwrap in the src slot so it becomes 1414 * a non-sensitive object, then, get all the attributes 1415 * and create the object in the destination slot 1416 */ 1417 1418 1419 if (wrap_info.class == CKO_SECRET_KEY) { 1420 /* unwrap with same key used for wrapping */ 1421 rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey( 1422 src_slot_session->hSession, 1423 &wrappingMech, wrappingKey, wrappedKey, 1424 wrappedKeyLen, unwrap_template, 1425 unwrap_template_size, &(unwrapped_obj)); 1426 } else { 1427 /* 1428 * If the object is wrapping with RSA public key, need 1429 * need to create RSA private key for unwrapping 1430 */ 1431 wrap_info.class = CKO_PRIVATE_KEY; 1432 rv = create_wrap_unwrap_key(src_slot_session, 1433 &unwrappingKey, &wrap_info, key_data, key_len); 1434 if (rv != CKR_OK) { 1435 goto finish; 1436 } 1437 rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey( 1438 src_slot_session->hSession, 1439 &wrappingMech, unwrappingKey, wrappedKey, 1440 wrappedKeyLen, unwrap_template, 1441 unwrap_template_size, &(unwrapped_obj)); 1442 } 1443 1444 1445 if (rv != CKR_OK) { 1446 goto finish; 1447 } 1448 1449 rv = meta_session_alloc(&tmp_meta_session); 1450 if (rv != CKR_OK) { 1451 goto finish; 1452 } 1453 1454 tmp_meta_session->session_flags = CKF_SERIAL_SESSION; 1455 1456 rv = meta_object_alloc(tmp_meta_session, &tmp_meta_obj); 1457 if (rv != CKR_OK) { 1458 goto finish; 1459 } 1460 1461 rv = meta_slot_object_alloc(&tmp_slot_obj); 1462 if (rv != CKR_OK) { 1463 goto finish; 1464 } 1465 1466 tmp_meta_obj->master_clone_slotnum = src_slot_session->slotnum; 1467 tmp_slot_obj->hObject = unwrapped_obj; 1468 tmp_meta_obj->clones[tmp_meta_obj->master_clone_slotnum] 1469 = tmp_slot_obj; 1470 meta_slot_object_activate(tmp_slot_obj, src_slot_session, 1471 B_FALSE); 1472 tmp_slot_obj = NULL; 1473 1474 rv = clone_by_create(tmp_meta_obj, new_clone, 1475 dst_slot_session); 1476 if (rv != CKR_OK) { 1477 goto finish; 1478 } 1479 } 1480 1481 finish: 1482 if (unwrappingKey) { 1483 (void) FUNCLIST(dst_slot_session->fw_st_id)->C_DestroyObject( 1484 dst_slot_session->hSession, unwrappingKey); 1485 } 1486 1487 if (wrappingKey) { 1488 (void) FUNCLIST(src_slot_session->fw_st_id)->C_DestroyObject( 1489 src_slot_session->hSession, wrappingKey); 1490 } 1491 1492 if (tmp_slot_obj) { 1493 (void) meta_slot_object_dealloc(tmp_slot_obj); 1494 } 1495 1496 if (tmp_meta_obj) { 1497 (void) meta_object_dealloc(tmp_meta_obj, B_TRUE); 1498 } 1499 1500 if (tmp_meta_session) { 1501 (void) meta_session_dealloc(tmp_meta_session); 1502 } 1503 1504 if (wrappedKey) { 1505 free(wrappedKey); 1506 } 1507 1508 if (src_slot_session) { 1509 meta_release_slot_session(src_slot_session); 1510 } 1511 1512 return (rv); 1513 1514 } 1515 1516 1517 /* 1518 * meta_object_get_clone 1519 * 1520 * Creates a "clone" of a metaobject on the specified slot. A clone is a 1521 * copy of the object. 1522 * 1523 * Clones are cached, so that they can be reused with subsquent operations. 1524 */ 1525 CK_RV 1526 meta_object_get_clone(meta_object_t *object, 1527 CK_ULONG slot_num, slot_session_t *slot_session, 1528 slot_object_t **clone) 1529 { 1530 CK_RV rv = CKR_OK; 1531 slot_object_t *newclone = NULL; 1532 1533 /* Does a clone already exist? */ 1534 if (object->clones[slot_num] != NULL) { 1535 *clone = object->clones[slot_num]; 1536 return (CKR_OK); 1537 } 1538 1539 if ((object->isSensitive) && (object->isToken) && 1540 (!metaslot_auto_key_migrate)) { 1541 /* 1542 * if the object is a sensitive token object, and auto 1543 * key migrate is not allowed, will not create the clone 1544 * in another slot 1545 */ 1546 return (CKR_FUNCTION_FAILED); 1547 } 1548 1549 /* object attributes can't be extracted and attributes are not known */ 1550 if ((!object->isExtractable) && (object->attributes == NULL)) { 1551 return (CKR_FUNCTION_FAILED); 1552 } 1553 1554 (void) pthread_mutex_lock(&object->clone_create_lock); 1555 1556 /* Maybe someone just created one? */ 1557 if (object->clones[slot_num] != NULL) { 1558 *clone = object->clones[slot_num]; 1559 goto finish; 1560 } 1561 1562 /* 1563 * has an attempt already been made to create this object in 1564 * slot? If yes, and there's no clone, as indicated above, 1565 * that means this object can't be created in this slot. 1566 */ 1567 if (object->tried_create_clone[slot_num]) { 1568 (void) pthread_mutex_unlock(&object->clone_create_lock); 1569 return (CKR_FUNCTION_FAILED); 1570 } 1571 1572 rv = meta_slot_object_alloc(&newclone); 1573 if (rv != CKR_OK) 1574 goto finish; 1575 1576 object->tried_create_clone[slot_num] = B_TRUE; 1577 1578 /* 1579 * If this object is sensitive and we do not have not copied in the 1580 * attributes via FreeObject functionality, then we need to wrap it off 1581 * the provider. If we do have attributes, we can just create the 1582 * clone 1583 */ 1584 1585 if (object->isSensitive && object->attributes == NULL) { 1586 rv = clone_by_wrap(object, newclone, slot_session); 1587 } else { 1588 rv = clone_by_create(object, newclone, slot_session); 1589 } 1590 1591 if (rv != CKR_OK) { 1592 goto finish; 1593 } 1594 1595 object->clones[slot_num] = newclone; 1596 meta_slot_object_activate(newclone, slot_session, object->isToken); 1597 1598 *clone = newclone; 1599 newclone = NULL; 1600 finish: 1601 (void) pthread_mutex_unlock(&object->clone_create_lock); 1602 1603 if (newclone) 1604 meta_slot_object_dealloc(newclone); 1605 1606 return (rv); 1607 } 1608 1609 1610 /* 1611 * meta_setup_clone_template 1612 * 1613 * Create a clone template for the specified object. 1614 */ 1615 static CK_RV 1616 meta_clone_template_setup(meta_object_t *object, 1617 const generic_attr_t *attributes, size_t num_attributes) 1618 { 1619 CK_RV rv = CKR_OK; 1620 CK_ATTRIBUTE *clone_template; 1621 size_t i, c = 0; 1622 1623 clone_template = malloc(num_attributes * sizeof (CK_ATTRIBUTE)); 1624 if (clone_template == NULL) { 1625 rv = CKR_HOST_MEMORY; 1626 goto finish; 1627 } 1628 1629 /* Don't allow attributes to change while we look at them. */ 1630 (void) pthread_rwlock_rdlock(&object->attribute_lock); 1631 1632 for (i = 0; i < num_attributes; i++) { 1633 if (!attributes[i].isCloneAttr || 1634 (attributes[i].attribute.type == CKA_TOKEN && 1635 object->isFreeToken == FREE_DISABLED)) { 1636 continue; 1637 } 1638 if ((!(attributes[i].hasValueForClone)) && 1639 (attributes[i].canBeEmptyValue)) { 1640 continue; 1641 } 1642 1643 clone_template[c].type = attributes[i].attribute.type; 1644 clone_template[c].ulValueLen = 1645 attributes[i].attribute.ulValueLen; 1646 /* Allocate space to store the attribute value. */ 1647 clone_template[c].pValue = malloc(clone_template[c].ulValueLen); 1648 if (clone_template[c].pValue == NULL) { 1649 rv = CKR_HOST_MEMORY; 1650 (void) pthread_rwlock_unlock(&object->attribute_lock); 1651 goto finish; 1652 } 1653 1654 (void) memcpy(clone_template[c].pValue, 1655 object->attributes[i].attribute.pValue, 1656 clone_template[c].ulValueLen); 1657 c++; 1658 } 1659 1660 (void) pthread_rwlock_unlock(&object->attribute_lock); 1661 1662 object->clone_template = clone_template; 1663 object->clone_template_size = c; 1664 1665 finish: 1666 return (rv); 1667 } 1668 1669 1670 /* 1671 * meta_object_find_by_handle 1672 * 1673 * Search for an existing metaobject, using the object handle of a clone 1674 * on a particular slot. 1675 * 1676 * Returns a matching metaobject, or NULL if no match was found. 1677 */ 1678 meta_object_t * 1679 meta_object_find_by_handle(CK_OBJECT_HANDLE hObject, CK_ULONG slotnum, 1680 boolean_t token_only) 1681 { 1682 meta_object_t *object = NULL, *tmp_obj; 1683 meta_session_t *session; 1684 1685 if (!token_only) { 1686 (void) pthread_rwlock_rdlock(&meta_sessionlist_lock); 1687 session = meta_sessionlist_head; 1688 while (session != NULL) { 1689 /* lock the objects list while we look at it */ 1690 (void) pthread_rwlock_rdlock( 1691 &(session->object_list_lock)); 1692 tmp_obj = session->object_list_head; 1693 while (tmp_obj != NULL) { 1694 slot_object_t *slot_object; 1695 1696 (void) pthread_rwlock_rdlock( 1697 &(tmp_obj->object_lock)); 1698 slot_object = tmp_obj->clones[slotnum]; 1699 if (slot_object != NULL) { 1700 if (slot_object->hObject == hObject) { 1701 object = tmp_obj; 1702 } 1703 } 1704 (void) pthread_rwlock_unlock( 1705 &(tmp_obj->object_lock)); 1706 if (object != NULL) { 1707 break; 1708 } 1709 tmp_obj = tmp_obj->next; 1710 } 1711 (void) pthread_rwlock_unlock( 1712 &(session->object_list_lock)); 1713 if (object != NULL) { 1714 break; 1715 } 1716 session = session->next; 1717 } 1718 (void) pthread_rwlock_unlock(&meta_sessionlist_lock); 1719 } 1720 1721 if (object != NULL) { 1722 /* found the object, no need to look further */ 1723 return (object); 1724 } 1725 1726 /* 1727 * Look at list of token objects 1728 */ 1729 (void) pthread_rwlock_rdlock(&tokenobject_list_lock); 1730 tmp_obj = tokenobject_list_head; 1731 1732 while (tmp_obj != NULL) { 1733 slot_object_t *slot_object; 1734 1735 (void) pthread_rwlock_rdlock(&(tmp_obj->object_lock)); 1736 slot_object = tmp_obj->clones[slotnum]; 1737 if (slot_object != NULL) { 1738 if (slot_object->hObject == hObject) 1739 object = tmp_obj; 1740 } 1741 (void) pthread_rwlock_unlock(&(tmp_obj->object_lock)); 1742 if (object != NULL) { 1743 break; 1744 } 1745 tmp_obj = tmp_obj->next; 1746 } 1747 (void) pthread_rwlock_unlock(&tokenobject_list_lock); 1748 1749 return (object); 1750 } 1751 1752 CK_RV 1753 meta_token_object_deactivate(token_obj_type_t token_type) 1754 { 1755 meta_object_t *object, *tmp_object; 1756 CK_RV save_rv = CKR_OK, rv; 1757 1758 /* get a write lock on the token object list */ 1759 (void) pthread_rwlock_wrlock(&tokenobject_list_lock); 1760 1761 object = tokenobject_list_head; 1762 1763 /* go through each object and delete the one with matching type */ 1764 while (object != NULL) { 1765 tmp_object = object->next; 1766 1767 if ((token_type == ALL_TOKEN) || 1768 ((object->isPrivate) && (token_type == PRIVATE_TOKEN)) || 1769 ((!object->isPrivate) && (token_type == PUBLIC_TOKEN))) { 1770 rv = meta_object_deactivate(object, B_TRUE, B_FALSE); 1771 if ((rv != CKR_OK) && (save_rv == CKR_OK)) { 1772 save_rv = rv; 1773 goto finish; 1774 } 1775 rv = meta_object_dealloc(object, B_FALSE); 1776 if ((rv != CKR_OK) && (save_rv == CKR_OK)) { 1777 save_rv = rv; 1778 goto finish; 1779 } 1780 } 1781 object = tmp_object; 1782 } 1783 finish: 1784 (void) pthread_rwlock_unlock(&tokenobject_list_lock); 1785 return (save_rv); 1786 } 1787 1788 /* 1789 * This function adds the to-be-freed meta object to a linked list. 1790 * When the number of objects queued in the linked list reaches the 1791 * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first 1792 * object (FIFO) in the list. 1793 */ 1794 void 1795 meta_object_delay_free(meta_object_t *objp) 1796 { 1797 meta_object_t *tmp; 1798 1799 (void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex); 1800 1801 /* Add the newly deleted object at the end of the list */ 1802 objp->next = NULL; 1803 if (obj_delay_freed.first == NULL) { 1804 obj_delay_freed.last = objp; 1805 obj_delay_freed.first = objp; 1806 } else { 1807 obj_delay_freed.last->next = objp; 1808 obj_delay_freed.last = objp; 1809 } 1810 1811 if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) { 1812 /* 1813 * Free the first object in the list only if 1814 * the total count reaches maximum threshold. 1815 */ 1816 obj_delay_freed.count--; 1817 tmp = obj_delay_freed.first->next; 1818 free(obj_delay_freed.first); 1819 obj_delay_freed.first = tmp; 1820 } 1821 (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex); 1822 } 1823 1824 1825 /* 1826 * This function checks if the object passed can be a freeobject. 1827 * 1828 * If there is more than one provider that supports the supported freeobject 1829 * mechanisms then allow freeobjects to be an option. 1830 */ 1831 1832 boolean_t 1833 meta_freeobject_check(meta_session_t *session, meta_object_t *object, 1834 CK_MECHANISM *pMech, CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len, 1835 CK_KEY_TYPE keytype) 1836 { 1837 mech_support_info_t *info = &(session->mech_support_info); 1838 1839 /* 1840 * If key migration is turned off, or the object does not has any of 1841 * the required flags and there is only one slot, then we don't need 1842 * FreeObjects. 1843 */ 1844 if (!metaslot_auto_key_migrate || 1845 (!object->isToken && !object->isSensitive && 1846 meta_slotManager_get_slotcount() < 2)) 1847 goto failure; 1848 1849 /* 1850 * If this call is for key generation, check pMech for supported 1851 * FreeObject mechs 1852 */ 1853 if (pMech != NULL) { 1854 if (pMech->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN || 1855 pMech->mechanism == CKM_EC_KEY_PAIR_GEN || 1856 pMech->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN || 1857 pMech->mechanism == CKM_DH_PKCS_DERIVE) 1858 info->mech = pMech->mechanism; 1859 else 1860 goto failure; 1861 1862 /* 1863 * If this call is for an object creation, look inside the template 1864 * for supported FreeObject mechs 1865 */ 1866 } else if (tmpl_len > 0) { 1867 if (!get_template_ulong(CKA_KEY_TYPE, tmpl, tmpl_len, &keytype)) 1868 goto failure; 1869 1870 switch (keytype) { 1871 case CKK_RSA: 1872 info->mech = CKM_RSA_PKCS_KEY_PAIR_GEN; 1873 break; 1874 case CKK_EC: 1875 info->mech = CKM_EC_KEY_PAIR_GEN; 1876 break; 1877 case CKK_DH: 1878 info->mech = CKM_DH_PKCS_KEY_PAIR_GEN; 1879 break; 1880 default: 1881 goto failure; 1882 } 1883 } else 1884 goto failure; 1885 1886 /* Get the slot that support this mech... */ 1887 if (meta_mechManager_get_slots(info, B_FALSE, NULL) != CKR_OK) 1888 goto failure; 1889 1890 /* 1891 * If there is only one slot with the mech or the first slot in 1892 * the list is the keystore slot, we should bail. 1893 */ 1894 if (info->num_supporting_slots < 2 && 1895 info->supporting_slots[0]->slotnum == get_keystore_slotnum()) 1896 goto failure; 1897 1898 if (object->isToken) 1899 object->isFreeToken = FREE_ALLOWED_KEY; 1900 else 1901 object->isFreeToken = FREE_DISABLED; 1902 1903 object->isFreeObject = FREE_ALLOWED_KEY; 1904 1905 return (B_TRUE); 1906 1907 failure: 1908 object->isFreeToken = FREE_DISABLED; 1909 object->isFreeObject = FREE_DISABLED; 1910 return (B_FALSE); 1911 } 1912 1913 /* 1914 * This function assumes meta_freeobject_check() has just been called and set 1915 * the isFreeObject and/or isFreeToken vars to FREE_ALLOWED_KEY. 1916 * 1917 * If the template value for CKA_PRIVATE, CKA_SENSITIVE and/or CKA_TOKEN are 1918 * true, then isFreeObject is fully enabled. In addition isFreeToken is 1919 * enabled if is CKA_TOKEN true. 1920 * 1921 * If create is true, we are doing a C_CreateObject operation and don't 1922 * handle CKA_PRIVATE & CKA_SENSITIVE flags, we only care about CKA_TOKEN. 1923 */ 1924 1925 boolean_t 1926 meta_freeobject_set(meta_object_t *object, CK_ATTRIBUTE *tmpl, 1927 CK_ULONG tmpl_len, boolean_t create) 1928 { 1929 1930 /* This check should never be true, if it is, it's a bug */ 1931 if (object->isFreeObject < FREE_ALLOWED_KEY) 1932 return (B_FALSE); 1933 1934 if (!create) { 1935 /* Turn off the Sensitive flag */ 1936 if (object->isSensitive) { 1937 if (set_template_boolean(CKA_SENSITIVE, tmpl, tmpl_len, 1938 B_TRUE, &falsevalue) == -1) 1939 goto failure; 1940 1941 object->isFreeObject = FREE_ENABLED; 1942 } 1943 1944 /* Turn off the Private flag */ 1945 if (object->isPrivate) { 1946 if (set_template_boolean(CKA_PRIVATE, tmpl, tmpl_len, 1947 B_TRUE, &falsevalue) == -1) 1948 goto failure; 1949 1950 object->isFreeObject = FREE_ENABLED; 1951 } 1952 } 1953 1954 if (object->isToken) { 1955 object->isToken = B_FALSE; 1956 object->isFreeToken = FREE_ENABLED; 1957 object->isFreeObject = FREE_ENABLED; 1958 } else 1959 object->isFreeToken = FREE_DISABLED; 1960 1961 /* 1962 * If isFreeObject is not in the FREE_ENABLED state yet, it can be 1963 * turned off because the object doesn't not need to be a FreeObject. 1964 */ 1965 if (object->isFreeObject == FREE_ALLOWED_KEY) 1966 object->isFreeObject = FREE_DISABLED; 1967 1968 return (B_TRUE); 1969 1970 failure: 1971 object->isFreeToken = FREE_DISABLED; 1972 object->isFreeObject = FREE_DISABLED; 1973 return (B_FALSE); 1974 } 1975 1976 /* 1977 * This function sets the CKA_TOKEN flag on a given object template depending 1978 * if the slot being used is a keystore. 1979 * 1980 * If the object is a token, but the slot is not the system keystore or has 1981 * no keystore, then set the template to token = false; otherwise it's true. 1982 * In addition we know ahead of time what the value is, so if the value is 1983 * already correct, bypass the setting function 1984 */ 1985 CK_RV 1986 meta_freetoken_set(CK_ULONG slot_num, CK_BBOOL *current_value, 1987 CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len) 1988 { 1989 1990 if (slot_num == get_keystore_slotnum()) { 1991 if (*current_value == TRUE) 1992 return (CKR_OK); 1993 1994 if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE, 1995 &truevalue) == -1) 1996 return (CKR_FUNCTION_FAILED); 1997 1998 } else { 1999 2000 if (*current_value == FALSE) 2001 return (CKR_OK); 2002 2003 if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE, 2004 &falsevalue) == -1) 2005 return (CKR_FUNCTION_FAILED); 2006 2007 *current_value = FALSE; 2008 } 2009 2010 return (CKR_OK); 2011 } 2012 2013 /* 2014 * Cloning function for meta_freeobject_clone() to use. This function 2015 * is streamlined because we know what the object is and this should 2016 * not be called as a generic cloner. 2017 */ 2018 2019 static CK_RV 2020 meta_freeobject_clone_maker(meta_session_t *session, meta_object_t *object, 2021 CK_ULONG slotnum) 2022 { 2023 2024 slot_object_t *slot_object = NULL; 2025 slot_session_t *slot_session = NULL; 2026 CK_RV rv; 2027 2028 rv = meta_slot_object_alloc(&slot_object); 2029 if (rv != CKR_OK) 2030 goto cleanup; 2031 2032 rv = meta_get_slot_session(slotnum, &slot_session, 2033 session->session_flags); 2034 if (rv != CKR_OK) 2035 goto cleanup; 2036 2037 rv = clone_by_create(object, slot_object, slot_session); 2038 if (rv == CKR_OK) { 2039 object->clones[slotnum] = slot_object; 2040 meta_slot_object_activate(slot_object, slot_session, B_TRUE); 2041 } 2042 2043 cleanup: 2044 meta_release_slot_session(slot_session); 2045 return (rv); 2046 2047 } 2048 2049 /* 2050 * This function is called when a object is a FreeObject. 2051 * 2052 * What we are given is an object that has been generated on a provider 2053 * that is not its final usage place. That maybe because: 2054 * 1) it's a token and needs to be stored in keystore. 2055 * 2) it was to be a private/sensitive object that we modified so we could know 2056 * the important attributes for cloning before we make it private/sensitive. 2057 */ 2058 2059 boolean_t 2060 meta_freeobject_clone(meta_session_t *session, meta_object_t *object) 2061 { 2062 CK_RV rv; 2063 CK_ULONG keystore_slotnum; 2064 CK_ATTRIBUTE attr[2]; 2065 boolean_t failover = B_FALSE; 2066 2067 if (object->attributes == NULL) { 2068 rv = meta_object_copyin(object); 2069 if (rv != CKR_OK) 2070 return (rv); 2071 } 2072 2073 if (object->isPrivate) { 2074 CK_OBJECT_HANDLE new_clone; 2075 CK_ULONG slotnum = object->master_clone_slotnum; 2076 slot_session_t *slot_session; 2077 2078 attr[0].type = CKA_PRIVATE; 2079 attr[0].pValue = &truevalue; 2080 attr[0].ulValueLen = sizeof (truevalue); 2081 2082 /* Set the master attribute list */ 2083 rv = attribute_set_value(attr, object->attributes, 2084 object->num_attributes); 2085 if (rv > 0) 2086 return (CKR_FUNCTION_FAILED); 2087 2088 /* Get a slot session */ 2089 rv = meta_get_slot_session(slotnum, &slot_session, 2090 session->session_flags); 2091 if (rv > 0) 2092 return (rv); 2093 2094 /* Create the new CKA_PRIVATE one */ 2095 rv = FUNCLIST(slot_session->fw_st_id)->\ 2096 C_CopyObject(slot_session->hSession, 2097 object->clones[slotnum]->hObject, attr, 1, &new_clone); 2098 2099 if (rv == CKR_USER_NOT_LOGGED_IN) { 2100 /* 2101 * If the CopyObject fails, we may be using a provider 2102 * that has a keystore that is not the default 2103 * keystore set in metaslot or has object management 2104 * abilities. In which case we should write this 2105 * object to metaslot's keystore and let the failover. 2106 * rest of the function know we've changed providers. 2107 */ 2108 failover = B_TRUE; 2109 keystore_slotnum = get_keystore_slotnum(); 2110 if (object->clones[keystore_slotnum] == NULL) { 2111 rv = meta_freeobject_clone_maker(session, 2112 object, keystore_slotnum); 2113 if (rv != CKR_OK) { 2114 goto failure; 2115 } 2116 } 2117 object->master_clone_slotnum = keystore_slotnum; 2118 2119 } else if (rv != CKR_OK) { 2120 meta_release_slot_session(slot_session); 2121 goto failure; 2122 } 2123 /* Remove the old object */ 2124 rv = FUNCLIST(slot_session->fw_st_id)-> \ 2125 C_DestroyObject(slot_session->hSession, 2126 object->clones[slotnum]->hObject); 2127 if (rv != CKR_OK) { 2128 meta_release_slot_session(slot_session); 2129 goto failure; 2130 } 2131 2132 if (!failover) 2133 object->clones[slotnum]->hObject = new_clone; 2134 else 2135 object->clones[slotnum] = NULL; 2136 2137 meta_release_slot_session(slot_session); 2138 2139 } 2140 2141 if (object->isSensitive) { 2142 slot_session_t *slot_session; 2143 CK_ULONG slotnum = object->master_clone_slotnum; 2144 2145 attr[0].type = CKA_SENSITIVE; 2146 attr[0].pValue = &truevalue; 2147 attr[0].ulValueLen = sizeof (truevalue); 2148 rv = attribute_set_value(attr, object->attributes, 2149 object->num_attributes); 2150 if (rv != CKR_OK) 2151 goto failure; 2152 2153 rv = meta_get_slot_session(slotnum, &slot_session, 2154 session->session_flags); 2155 if (rv == CKR_OK) { 2156 rv = FUNCLIST(slot_session->fw_st_id)-> \ 2157 C_SetAttributeValue(slot_session->hSession, 2158 object->clones[slotnum]->hObject, attr, 1); 2159 2160 meta_release_slot_session(slot_session); 2161 } 2162 } 2163 2164 if (object->isFreeToken == FREE_ENABLED || failover) { 2165 keystore_slotnum = get_keystore_slotnum(); 2166 if (object->clones[keystore_slotnum] == NULL) { 2167 rv = meta_freeobject_clone_maker(session, object, 2168 keystore_slotnum); 2169 if (rv != CKR_OK) 2170 goto failure; 2171 2172 object->master_clone_slotnum = keystore_slotnum; 2173 } 2174 object->isFreeToken = FREE_ENABLED; 2175 } 2176 2177 object->isFreeObject = FREE_ENABLED; 2178 return (CKR_OK); 2179 2180 failure: 2181 object->isFreeToken = FREE_DISABLED; 2182 object->isFreeObject = FREE_DISABLED; 2183 return (rv); 2184 2185 } 2186