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 /* 1555 * has an attempt already been made to create this object in 1556 * slot? If yes, and there's no clone, as indicated above, 1557 * that means this object can't be created in this slot. 1558 */ 1559 if (object->tried_create_clone[slot_num]) { 1560 return (CKR_FUNCTION_FAILED); 1561 } 1562 (void) pthread_mutex_lock(&object->clone_create_lock); 1563 1564 /* Maybe someone just created one? */ 1565 if (object->clones[slot_num] != NULL) { 1566 *clone = object->clones[slot_num]; 1567 goto finish; 1568 } 1569 1570 rv = meta_slot_object_alloc(&newclone); 1571 if (rv != CKR_OK) 1572 goto finish; 1573 1574 object->tried_create_clone[slot_num] = B_TRUE; 1575 1576 /* 1577 * If this object is sensitive and we do not have not copied in the 1578 * attributes via FreeObject functionality, then we need to wrap it off 1579 * the provider. If we do have attributes, we can just create the 1580 * clone 1581 */ 1582 1583 if (object->isSensitive && object->attributes == NULL) { 1584 rv = clone_by_wrap(object, newclone, slot_session); 1585 } else { 1586 rv = clone_by_create(object, newclone, slot_session); 1587 } 1588 1589 if (rv != CKR_OK) { 1590 goto finish; 1591 } 1592 1593 object->clones[slot_num] = newclone; 1594 meta_slot_object_activate(newclone, slot_session, object->isToken); 1595 1596 *clone = newclone; 1597 newclone = NULL; 1598 finish: 1599 (void) pthread_mutex_unlock(&object->clone_create_lock); 1600 1601 if (newclone) 1602 meta_slot_object_dealloc(newclone); 1603 1604 return (rv); 1605 } 1606 1607 1608 /* 1609 * meta_setup_clone_template 1610 * 1611 * Create a clone template for the specified object. 1612 */ 1613 static CK_RV 1614 meta_clone_template_setup(meta_object_t *object, 1615 const generic_attr_t *attributes, size_t num_attributes) 1616 { 1617 CK_RV rv = CKR_OK; 1618 CK_ATTRIBUTE *clone_template; 1619 size_t i, c = 0; 1620 1621 clone_template = malloc(num_attributes * sizeof (CK_ATTRIBUTE)); 1622 if (clone_template == NULL) { 1623 rv = CKR_HOST_MEMORY; 1624 goto finish; 1625 } 1626 1627 /* Don't allow attributes to change while we look at them. */ 1628 (void) pthread_rwlock_rdlock(&object->attribute_lock); 1629 1630 for (i = 0; i < num_attributes; i++) { 1631 if (!attributes[i].isCloneAttr || 1632 (attributes[i].attribute.type == CKA_TOKEN && 1633 object->isFreeToken == FREE_DISABLED)) { 1634 continue; 1635 } 1636 if ((!(attributes[i].hasValueForClone)) && 1637 (attributes[i].canBeEmptyValue)) { 1638 continue; 1639 } 1640 1641 clone_template[c].type = attributes[i].attribute.type; 1642 clone_template[c].ulValueLen = 1643 attributes[i].attribute.ulValueLen; 1644 /* Allocate space to store the attribute value. */ 1645 clone_template[c].pValue = malloc(clone_template[c].ulValueLen); 1646 if (clone_template[c].pValue == NULL) { 1647 rv = CKR_HOST_MEMORY; 1648 (void) pthread_rwlock_unlock(&object->attribute_lock); 1649 goto finish; 1650 } 1651 1652 (void) memcpy(clone_template[c].pValue, 1653 object->attributes[i].attribute.pValue, 1654 clone_template[c].ulValueLen); 1655 c++; 1656 } 1657 1658 (void) pthread_rwlock_unlock(&object->attribute_lock); 1659 1660 object->clone_template = clone_template; 1661 object->clone_template_size = c; 1662 1663 finish: 1664 return (rv); 1665 } 1666 1667 1668 /* 1669 * meta_object_find_by_handle 1670 * 1671 * Search for an existing metaobject, using the object handle of a clone 1672 * on a particular slot. 1673 * 1674 * Returns a matching metaobject, or NULL if no match was found. 1675 */ 1676 meta_object_t * 1677 meta_object_find_by_handle(CK_OBJECT_HANDLE hObject, CK_ULONG slotnum, 1678 boolean_t token_only) 1679 { 1680 meta_object_t *object = NULL, *tmp_obj; 1681 meta_session_t *session; 1682 1683 if (!token_only) { 1684 (void) pthread_rwlock_rdlock(&meta_sessionlist_lock); 1685 session = meta_sessionlist_head; 1686 while (session != NULL) { 1687 /* lock the objects list while we look at it */ 1688 (void) pthread_rwlock_rdlock( 1689 &(session->object_list_lock)); 1690 tmp_obj = session->object_list_head; 1691 while (tmp_obj != NULL) { 1692 slot_object_t *slot_object; 1693 1694 (void) pthread_rwlock_rdlock( 1695 &(tmp_obj->object_lock)); 1696 slot_object = tmp_obj->clones[slotnum]; 1697 if (slot_object != NULL) { 1698 if (slot_object->hObject == hObject) { 1699 object = tmp_obj; 1700 } 1701 } 1702 (void) pthread_rwlock_unlock( 1703 &(tmp_obj->object_lock)); 1704 if (object != NULL) { 1705 break; 1706 } 1707 tmp_obj = tmp_obj->next; 1708 } 1709 (void) pthread_rwlock_unlock( 1710 &(session->object_list_lock)); 1711 if (object != NULL) { 1712 break; 1713 } 1714 session = session->next; 1715 } 1716 (void) pthread_rwlock_unlock(&meta_sessionlist_lock); 1717 } 1718 1719 if (object != NULL) { 1720 /* found the object, no need to look further */ 1721 return (object); 1722 } 1723 1724 /* 1725 * Look at list of token objects 1726 */ 1727 (void) pthread_rwlock_rdlock(&tokenobject_list_lock); 1728 tmp_obj = tokenobject_list_head; 1729 1730 while (tmp_obj != NULL) { 1731 slot_object_t *slot_object; 1732 1733 (void) pthread_rwlock_rdlock(&(tmp_obj->object_lock)); 1734 slot_object = tmp_obj->clones[slotnum]; 1735 if (slot_object != NULL) { 1736 if (slot_object->hObject == hObject) 1737 object = tmp_obj; 1738 } 1739 (void) pthread_rwlock_unlock(&(tmp_obj->object_lock)); 1740 if (object != NULL) { 1741 break; 1742 } 1743 tmp_obj = tmp_obj->next; 1744 } 1745 (void) pthread_rwlock_unlock(&tokenobject_list_lock); 1746 1747 return (object); 1748 } 1749 1750 CK_RV 1751 meta_token_object_deactivate(token_obj_type_t token_type) 1752 { 1753 meta_object_t *object, *tmp_object; 1754 CK_RV save_rv = CKR_OK, rv; 1755 1756 /* get a write lock on the token object list */ 1757 (void) pthread_rwlock_wrlock(&tokenobject_list_lock); 1758 1759 object = tokenobject_list_head; 1760 1761 /* go through each object and delete the one with matching type */ 1762 while (object != NULL) { 1763 tmp_object = object->next; 1764 1765 if ((token_type == ALL_TOKEN) || 1766 ((object->isPrivate) && (token_type == PRIVATE_TOKEN)) || 1767 ((!object->isPrivate) && (token_type == PUBLIC_TOKEN))) { 1768 rv = meta_object_deactivate(object, B_TRUE, B_FALSE); 1769 if ((rv != CKR_OK) && (save_rv == CKR_OK)) { 1770 save_rv = rv; 1771 goto finish; 1772 } 1773 rv = meta_object_dealloc(object, B_FALSE); 1774 if ((rv != CKR_OK) && (save_rv == CKR_OK)) { 1775 save_rv = rv; 1776 goto finish; 1777 } 1778 } 1779 object = tmp_object; 1780 } 1781 finish: 1782 (void) pthread_rwlock_unlock(&tokenobject_list_lock); 1783 return (save_rv); 1784 } 1785 1786 /* 1787 * This function adds the to-be-freed meta object to a linked list. 1788 * When the number of objects queued in the linked list reaches the 1789 * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first 1790 * object (FIFO) in the list. 1791 */ 1792 void 1793 meta_object_delay_free(meta_object_t *objp) 1794 { 1795 meta_object_t *tmp; 1796 1797 (void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex); 1798 1799 /* Add the newly deleted object at the end of the list */ 1800 objp->next = NULL; 1801 if (obj_delay_freed.first == NULL) { 1802 obj_delay_freed.last = objp; 1803 obj_delay_freed.first = objp; 1804 } else { 1805 obj_delay_freed.last->next = objp; 1806 obj_delay_freed.last = objp; 1807 } 1808 1809 if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) { 1810 /* 1811 * Free the first object in the list only if 1812 * the total count reaches maximum threshold. 1813 */ 1814 obj_delay_freed.count--; 1815 tmp = obj_delay_freed.first->next; 1816 free(obj_delay_freed.first); 1817 obj_delay_freed.first = tmp; 1818 } 1819 (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex); 1820 } 1821 1822 1823 /* 1824 * This function checks if the object passed can be a freeobject. 1825 * 1826 * If there is more than one provider that supports the supported freeobject 1827 * mechanisms then allow freeobjects to be an option. 1828 */ 1829 1830 boolean_t 1831 meta_freeobject_check(meta_session_t *session, meta_object_t *object, 1832 CK_MECHANISM *pMech, CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len, 1833 CK_KEY_TYPE keytype) 1834 { 1835 mech_support_info_t *info = &(session->mech_support_info); 1836 1837 /* 1838 * If key migration is turned off, or the object does not has any of 1839 * the required flags and there is only one slot, then we don't need 1840 * FreeObjects. 1841 */ 1842 if (!metaslot_auto_key_migrate || 1843 (!object->isToken && !object->isSensitive && 1844 meta_slotManager_get_slotcount() < 2)) 1845 goto failure; 1846 1847 /* 1848 * If this call is for key generation, check pMech for supported 1849 * FreeObject mechs 1850 */ 1851 if (pMech != NULL) { 1852 if (pMech->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN || 1853 pMech->mechanism == CKM_EC_KEY_PAIR_GEN || 1854 pMech->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN || 1855 pMech->mechanism == CKM_DH_PKCS_DERIVE) 1856 info->mech = pMech->mechanism; 1857 else 1858 goto failure; 1859 1860 /* 1861 * If this call is for an object creation, look inside the template 1862 * for supported FreeObject mechs 1863 */ 1864 } else if (tmpl_len > 0) { 1865 if (!get_template_ulong(CKA_KEY_TYPE, tmpl, tmpl_len, &keytype)) 1866 goto failure; 1867 1868 switch (keytype) { 1869 case CKK_RSA: 1870 info->mech = CKM_RSA_PKCS_KEY_PAIR_GEN; 1871 break; 1872 case CKK_EC: 1873 info->mech = CKM_EC_KEY_PAIR_GEN; 1874 break; 1875 case CKK_DH: 1876 info->mech = CKM_DH_PKCS_KEY_PAIR_GEN; 1877 break; 1878 default: 1879 goto failure; 1880 } 1881 } else 1882 goto failure; 1883 1884 /* Get the slot that support this mech... */ 1885 if (meta_mechManager_get_slots(info, B_FALSE, NULL) != CKR_OK) 1886 goto failure; 1887 1888 /* 1889 * If there is only one slot with the mech or the first slot in 1890 * the list is the keystore slot, we should bail. 1891 */ 1892 if (info->num_supporting_slots < 2 && 1893 info->supporting_slots[0]->slotnum == get_keystore_slotnum()) 1894 goto failure; 1895 1896 if (object->isToken) 1897 object->isFreeToken = FREE_ALLOWED_KEY; 1898 else 1899 object->isFreeToken = FREE_DISABLED; 1900 1901 object->isFreeObject = FREE_ALLOWED_KEY; 1902 1903 return (B_TRUE); 1904 1905 failure: 1906 object->isFreeToken = FREE_DISABLED; 1907 object->isFreeObject = FREE_DISABLED; 1908 return (B_FALSE); 1909 } 1910 1911 /* 1912 * This function assumes meta_freeobject_check() has just been called and set 1913 * the isFreeObject and/or isFreeToken vars to FREE_ALLOWED_KEY. 1914 * 1915 * If the template value for CKA_PRIVATE, CKA_SENSITIVE and/or CKA_TOKEN are 1916 * true, then isFreeObject is fully enabled. In addition isFreeToken is 1917 * enabled if is CKA_TOKEN true. 1918 * 1919 * If create is true, we are doing a C_CreateObject operation and don't 1920 * handle CKA_PRIVATE & CKA_SENSITIVE flags, we only care about CKA_TOKEN. 1921 */ 1922 1923 boolean_t 1924 meta_freeobject_set(meta_object_t *object, CK_ATTRIBUTE *tmpl, 1925 CK_ULONG tmpl_len, boolean_t create) 1926 { 1927 1928 /* This check should never be true, if it is, it's a bug */ 1929 if (object->isFreeObject < FREE_ALLOWED_KEY) 1930 return (B_FALSE); 1931 1932 if (!create) { 1933 /* Turn off the Sensitive flag */ 1934 if (object->isSensitive) { 1935 if (set_template_boolean(CKA_SENSITIVE, tmpl, tmpl_len, 1936 B_TRUE, &falsevalue) == -1) 1937 goto failure; 1938 1939 object->isFreeObject = FREE_ENABLED; 1940 } 1941 1942 /* Turn off the Private flag */ 1943 if (object->isPrivate) { 1944 if (set_template_boolean(CKA_PRIVATE, tmpl, tmpl_len, 1945 B_TRUE, &falsevalue) == -1) 1946 goto failure; 1947 1948 object->isFreeObject = FREE_ENABLED; 1949 } 1950 } 1951 1952 if (object->isToken) { 1953 object->isToken = B_FALSE; 1954 object->isFreeToken = FREE_ENABLED; 1955 object->isFreeObject = FREE_ENABLED; 1956 } else 1957 object->isFreeToken = FREE_DISABLED; 1958 1959 /* 1960 * If isFreeObject is not in the FREE_ENABLED state yet, it can be 1961 * turned off because the object doesn't not need to be a FreeObject. 1962 */ 1963 if (object->isFreeObject == FREE_ALLOWED_KEY) 1964 object->isFreeObject = FREE_DISABLED; 1965 1966 return (B_TRUE); 1967 1968 failure: 1969 object->isFreeToken = FREE_DISABLED; 1970 object->isFreeObject = FREE_DISABLED; 1971 return (B_FALSE); 1972 } 1973 1974 /* 1975 * This function sets the CKA_TOKEN flag on a given object template depending 1976 * if the slot being used is a keystore. 1977 * 1978 * If the object is a token, but the slot is not the system keystore or has 1979 * no keystore, then set the template to token = false; otherwise it's true. 1980 * In addition we know ahead of time what the value is, so if the value is 1981 * already correct, bypass the setting function 1982 */ 1983 CK_RV 1984 meta_freetoken_set(CK_ULONG slot_num, CK_BBOOL *current_value, 1985 CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len) 1986 { 1987 1988 if (slot_num == get_keystore_slotnum()) { 1989 if (*current_value == TRUE) 1990 return (CKR_OK); 1991 1992 if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE, 1993 &truevalue) == -1) 1994 return (CKR_FUNCTION_FAILED); 1995 1996 } else { 1997 1998 if (*current_value == FALSE) 1999 return (CKR_OK); 2000 2001 if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE, 2002 &falsevalue) == -1) 2003 return (CKR_FUNCTION_FAILED); 2004 2005 *current_value = FALSE; 2006 } 2007 2008 return (CKR_OK); 2009 } 2010 2011 /* 2012 * Cloning function for meta_freeobject_clone() to use. This function 2013 * is streamlined because we know what the object is and this should 2014 * not be called as a generic cloner. 2015 */ 2016 2017 static CK_RV 2018 meta_freeobject_clone_maker(meta_session_t *session, meta_object_t *object, 2019 CK_ULONG slotnum) 2020 { 2021 2022 slot_object_t *slot_object = NULL; 2023 slot_session_t *slot_session = NULL; 2024 CK_RV rv; 2025 2026 rv = meta_slot_object_alloc(&slot_object); 2027 if (rv != CKR_OK) 2028 goto cleanup; 2029 2030 rv = meta_get_slot_session(slotnum, &slot_session, 2031 session->session_flags); 2032 if (rv != CKR_OK) 2033 goto cleanup; 2034 2035 rv = clone_by_create(object, slot_object, slot_session); 2036 if (rv == CKR_OK) { 2037 object->clones[slotnum] = slot_object; 2038 meta_slot_object_activate(slot_object, slot_session, B_TRUE); 2039 } 2040 2041 cleanup: 2042 meta_release_slot_session(slot_session); 2043 return (rv); 2044 2045 } 2046 2047 /* 2048 * This function is called when a object is a FreeObject. 2049 * 2050 * What we are given is an object that has been generated on a provider 2051 * that is not its final usage place. That maybe because: 2052 * 1) it's a token and needs to be stored in keystore. 2053 * 2) it was to be a private/sensitive object that we modified so we could know 2054 * the important attributes for cloning before we make it private/sensitive. 2055 */ 2056 2057 boolean_t 2058 meta_freeobject_clone(meta_session_t *session, meta_object_t *object) 2059 { 2060 CK_RV rv; 2061 CK_ULONG keystore_slotnum; 2062 CK_ATTRIBUTE attr[2]; 2063 boolean_t failover = B_FALSE; 2064 2065 if (object->attributes == NULL) { 2066 rv = meta_object_copyin(object); 2067 if (rv != CKR_OK) 2068 return (rv); 2069 } 2070 2071 if (object->isPrivate) { 2072 CK_OBJECT_HANDLE new_clone; 2073 CK_ULONG slotnum = object->master_clone_slotnum; 2074 slot_session_t *slot_session; 2075 2076 attr[0].type = CKA_PRIVATE; 2077 attr[0].pValue = &truevalue; 2078 attr[0].ulValueLen = sizeof (truevalue); 2079 2080 /* Set the master attribute list */ 2081 rv = attribute_set_value(attr, object->attributes, 2082 object->num_attributes); 2083 if (rv > 0) 2084 return (CKR_FUNCTION_FAILED); 2085 2086 /* Get a slot session */ 2087 rv = meta_get_slot_session(slotnum, &slot_session, 2088 session->session_flags); 2089 if (rv > 0) 2090 return (rv); 2091 2092 /* Create the new CKA_PRIVATE one */ 2093 rv = FUNCLIST(slot_session->fw_st_id)->\ 2094 C_CopyObject(slot_session->hSession, 2095 object->clones[slotnum]->hObject, attr, 1, &new_clone); 2096 2097 if (rv == CKR_USER_NOT_LOGGED_IN) { 2098 /* 2099 * If the CopyObject fails, we may be using a provider 2100 * that has a keystore that is not the default 2101 * keystore set in metaslot or has object management 2102 * abilities. In which case we should write this 2103 * object to metaslot's keystore and let the failover. 2104 * rest of the function know we've changed providers. 2105 */ 2106 failover = B_TRUE; 2107 keystore_slotnum = get_keystore_slotnum(); 2108 if (object->clones[keystore_slotnum] == NULL) { 2109 rv = meta_freeobject_clone_maker(session, 2110 object, keystore_slotnum); 2111 if (rv != CKR_OK) { 2112 goto failure; 2113 } 2114 } 2115 object->master_clone_slotnum = keystore_slotnum; 2116 2117 } else if (rv != CKR_OK) { 2118 meta_release_slot_session(slot_session); 2119 goto failure; 2120 } 2121 /* Remove the old object */ 2122 rv = FUNCLIST(slot_session->fw_st_id)-> \ 2123 C_DestroyObject(slot_session->hSession, 2124 object->clones[slotnum]->hObject); 2125 if (rv != CKR_OK) { 2126 meta_release_slot_session(slot_session); 2127 goto failure; 2128 } 2129 2130 if (!failover) 2131 object->clones[slotnum]->hObject = new_clone; 2132 else 2133 object->clones[slotnum] = NULL; 2134 2135 meta_release_slot_session(slot_session); 2136 2137 } 2138 2139 if (object->isSensitive) { 2140 slot_session_t *slot_session; 2141 CK_ULONG slotnum = object->master_clone_slotnum; 2142 2143 attr[0].type = CKA_SENSITIVE; 2144 attr[0].pValue = &truevalue; 2145 attr[0].ulValueLen = sizeof (truevalue); 2146 rv = attribute_set_value(attr, object->attributes, 2147 object->num_attributes); 2148 if (rv != CKR_OK) 2149 goto failure; 2150 2151 rv = meta_get_slot_session(slotnum, &slot_session, 2152 session->session_flags); 2153 if (rv == CKR_OK) { 2154 rv = FUNCLIST(slot_session->fw_st_id)-> \ 2155 C_SetAttributeValue(slot_session->hSession, 2156 object->clones[slotnum]->hObject, attr, 1); 2157 2158 meta_release_slot_session(slot_session); 2159 } 2160 } 2161 2162 if (object->isFreeToken == FREE_ENABLED || failover) { 2163 keystore_slotnum = get_keystore_slotnum(); 2164 if (object->clones[keystore_slotnum] == NULL) { 2165 rv = meta_freeobject_clone_maker(session, object, 2166 keystore_slotnum); 2167 if (rv != CKR_OK) 2168 goto failure; 2169 2170 object->master_clone_slotnum = keystore_slotnum; 2171 } 2172 object->isFreeToken = FREE_ENABLED; 2173 } 2174 2175 object->isFreeObject = FREE_ENABLED; 2176 return (CKR_OK); 2177 2178 failure: 2179 object->isFreeToken = FREE_DISABLED; 2180 object->isFreeObject = FREE_DISABLED; 2181 return (rv); 2182 2183 } 2184