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