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