1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <cryptoutil.h> 29 #include <errno.h> 30 #include <fcntl.h> 31 #include <stdio.h> 32 #include <strings.h> 33 #include "metaGlobal.h" 34 35 /* 36 * meta_operation_init 37 * 38 */ 39 CK_RV 40 meta_operation_init(CK_FLAGS optype, meta_session_t *session, 41 CK_MECHANISM *pMechanism, meta_object_t *key) 42 { 43 CK_RV rv, save_rv; 44 mechinfo_t **supporting_slots; 45 CK_ULONG slotnum; 46 unsigned long i, slotCount = 0; 47 slot_session_t *init_session = NULL; 48 CK_MECHANISM_INFO mech_info; 49 50 /* 51 * If an operation is already active, cleanup existing operation 52 * and start a new one. 53 */ 54 if (session->op1.type != 0) { 55 meta_operation_cleanup(session, session->op1.type, B_FALSE); 56 } 57 58 mech_info.flags = optype; 59 60 /* 61 * Get a list of capable slots. 62 * 63 * If the specified mechanism is used in this session last time, 64 * the list of capable slots is already retrieved. We can save 65 * some processing, and just use that list of slots. 66 */ 67 if (((session->mech_support_info).mech != pMechanism->mechanism) || 68 ((session->mech_support_info).num_supporting_slots == 0)) { 69 (session->mech_support_info).mech = pMechanism->mechanism; 70 rv = meta_mechManager_get_slots(&(session->mech_support_info), 71 B_FALSE, &mech_info); 72 if (rv != CKR_OK) { 73 goto finish; 74 } 75 } 76 77 rv = CKR_FUNCTION_FAILED; 78 79 /* The following 2 assignment is just to make the code more readable */ 80 slotCount = (session->mech_support_info).num_supporting_slots; 81 supporting_slots = (session->mech_support_info).supporting_slots; 82 83 /* Attempt to initialize operation on slots until one succeeds. */ 84 for (i = 0; i < slotCount; i++) { 85 slot_object_t *init_key; 86 CK_SLOT_ID fw_st_id; 87 88 init_session = NULL; 89 90 slotnum = supporting_slots[i]->slotnum; 91 92 /* 93 * An actual session with the underlying slot is required 94 * for the operation. When the operation is successfully 95 * completed, the underlying session with the slot 96 * is not released back to the list of available sessions 97 * pool. This will help if the next operation can 98 * also be done on the same slot, because it avoids 99 * one extra trip to the session pool to get an idle session. 100 * If the operation can't be done on that slot, 101 * we release the session back to the session pool then. 102 */ 103 if (session->op1.session != NULL) { 104 105 if ((session->op1.session)->slotnum == slotnum) { 106 init_session = session->op1.session; 107 /* 108 * set it to NULL for now, assign it to 109 * init_session again if it is successful 110 */ 111 session->op1.session = NULL; 112 } else { 113 init_session = NULL; 114 } 115 116 } 117 118 if (!init_session) { 119 rv = meta_get_slot_session(slotnum, &init_session, 120 session->session_flags); 121 if (rv != CKR_OK) { 122 goto loop_cleanup; 123 } 124 } 125 126 /* if necessary, ensure a clone of the obj exists in slot */ 127 if (optype != CKF_DIGEST) { 128 rv = meta_object_get_clone(key, slotnum, init_session, 129 &init_key); 130 131 if (rv != CKR_OK) { 132 goto loop_cleanup; 133 } 134 } 135 136 fw_st_id = init_session->fw_st_id; 137 switch (optype) { 138 case CKF_ENCRYPT: 139 rv = FUNCLIST(fw_st_id)->C_EncryptInit( 140 init_session->hSession, pMechanism, 141 init_key->hObject); 142 break; 143 case CKF_DECRYPT: 144 rv = FUNCLIST(fw_st_id)->C_DecryptInit( 145 init_session->hSession, pMechanism, 146 init_key->hObject); 147 break; 148 case CKF_DIGEST: 149 rv = FUNCLIST(fw_st_id)->C_DigestInit( 150 init_session->hSession, pMechanism); 151 break; 152 case CKF_SIGN: 153 rv = FUNCLIST(fw_st_id)->C_SignInit( 154 init_session->hSession, pMechanism, 155 init_key->hObject); 156 break; 157 case CKF_VERIFY: 158 rv = FUNCLIST(fw_st_id)->C_VerifyInit( 159 init_session->hSession, pMechanism, 160 init_key->hObject); 161 break; 162 case CKF_SIGN_RECOVER: 163 rv = FUNCLIST(fw_st_id)->C_SignRecoverInit( 164 init_session->hSession, pMechanism, 165 init_key->hObject); 166 break; 167 case CKF_VERIFY_RECOVER: 168 rv = FUNCLIST(fw_st_id)->C_VerifyRecoverInit( 169 init_session->hSession, pMechanism, 170 init_key->hObject); 171 break; 172 173 default: 174 /*NOTREACHED*/ 175 rv = CKR_FUNCTION_FAILED; 176 break; 177 } 178 179 if (rv == CKR_OK) 180 break; 181 182 loop_cleanup: 183 if (i == 0) { 184 save_rv = rv; 185 } 186 187 if (init_session) { 188 meta_release_slot_session(init_session); 189 init_session = NULL; 190 } 191 192 } 193 194 if (rv == CKR_OK) { 195 196 /* 197 * If currently stored session is not the one being in use now, 198 * release the previous one and store the current one 199 */ 200 if ((session->op1.session) && 201 (session->op1.session != init_session)) { 202 meta_release_slot_session(session->op1.session); 203 } 204 205 /* Save the session */ 206 session->op1.session = init_session; 207 session->op1.type = optype; 208 } else { 209 rv = save_rv; 210 } 211 212 finish: 213 return (rv); 214 } 215 216 /* 217 * meta_do_operation 218 * 219 * NOTES: 220 * 221 * 1) The spec says you cannot do a C_Encrypt after a C_EncUpdate, 222 * but we don't explicitly enforce it here (ie, disallow doing MODE_SINGLE 223 * after a MODE_UPDATE). Instead, we just assume the underlying provider 224 * will catch the problem and return an appropriate error. 225 * 226 * 2) Note that the Verify operations are a little unusual, due to the 227 * PKCS#11 API. For C_Verify, the last two arguments are used as inputs, 228 * unlike the other single pass operations (where they are outputs). For 229 * C_VerifyFinal, in/inLen are passed instead of out/outLen like the other 230 * Final operations. 231 * 232 * 3) C_DigestKey is the only crypto operation that uses an object after 233 * the operation has been initialized. No other callers should provide 234 * this argument (use NULL). 235 */ 236 CK_RV 237 meta_do_operation(CK_FLAGS optype, int mode, 238 meta_session_t *session, meta_object_t *object, 239 CK_BYTE *in, CK_ULONG inLen, CK_BYTE *out, CK_ULONG *outLen) 240 { 241 CK_RV rv; 242 CK_SESSION_HANDLE hSession; 243 CK_SLOT_ID fw_st_id; 244 slot_session_t *slot_session = NULL; 245 slot_object_t *slot_object = NULL; 246 247 boolean_t shutdown, finished_normally; 248 249 if (optype != session->op1.type) { 250 return (CKR_OPERATION_NOT_INITIALIZED); 251 } 252 253 slot_session = session->op1.session; 254 255 if (slot_session) { 256 hSession = slot_session->hSession; 257 fw_st_id = slot_session->fw_st_id; 258 } else { 259 /* should never be here */ 260 return (CKR_FUNCTION_FAILED); 261 } 262 263 264 /* Do the operation... */ 265 if (optype == CKF_ENCRYPT && mode == MODE_SINGLE) { 266 rv = FUNCLIST(fw_st_id)->C_Encrypt(hSession, in, 267 inLen, out, outLen); 268 } else if (optype == CKF_ENCRYPT && mode == MODE_UPDATE) { 269 rv = FUNCLIST(fw_st_id)->C_EncryptUpdate(hSession, in, 270 inLen, out, outLen); 271 } else if (optype == CKF_ENCRYPT && mode == MODE_FINAL) { 272 rv = FUNCLIST(fw_st_id)->C_EncryptFinal(hSession, out, 273 outLen); 274 275 } else if (optype == CKF_DECRYPT && mode == MODE_SINGLE) { 276 rv = FUNCLIST(fw_st_id)->C_Decrypt(hSession, in, 277 inLen, out, outLen); 278 } else if (optype == CKF_DECRYPT && mode == MODE_UPDATE) { 279 rv = FUNCLIST(fw_st_id)->C_DecryptUpdate(hSession, in, 280 inLen, out, outLen); 281 } else if (optype == CKF_DECRYPT && mode == MODE_FINAL) { 282 rv = FUNCLIST(fw_st_id)->C_DecryptFinal(hSession, out, 283 outLen); 284 285 } else if (optype == CKF_DIGEST && mode == MODE_SINGLE) { 286 rv = FUNCLIST(fw_st_id)->C_Digest(hSession, in, inLen, 287 out, outLen); 288 } else if (optype == CKF_DIGEST && mode == MODE_UPDATE) { 289 /* noOutputForOp = TRUE; */ 290 rv = FUNCLIST(fw_st_id)->C_DigestUpdate(hSession, in, 291 inLen); 292 } else if (optype == CKF_DIGEST && mode == MODE_UPDATE_WITHKEY) { 293 /* noOutputForOp = TRUE; */ 294 /* 295 * For C_DigestKey, a key is provided and 296 * we need the clone. 297 */ 298 rv = meta_object_get_clone(object, 299 slot_session->slotnum, slot_session, &slot_object); 300 if (rv == CKR_OK) 301 rv = FUNCLIST(fw_st_id)->C_DigestKey(hSession, 302 slot_object->hObject); 303 } else if (optype == CKF_DIGEST && mode == MODE_FINAL) { 304 rv = FUNCLIST(fw_st_id)->C_DigestFinal(hSession, out, 305 outLen); 306 307 } else if (optype == CKF_SIGN && mode == MODE_SINGLE) { 308 rv = FUNCLIST(fw_st_id)->C_Sign(hSession, in, inLen, 309 out, outLen); 310 } else if (optype == CKF_SIGN && mode == MODE_UPDATE) { 311 /* noOutputForOp = TRUE; */ 312 rv = FUNCLIST(fw_st_id)->C_SignUpdate(hSession, in, 313 inLen); 314 } else if (optype == CKF_SIGN && mode == MODE_FINAL) { 315 rv = FUNCLIST(fw_st_id)->C_SignFinal(hSession, out, 316 outLen); 317 318 } else if (optype == CKF_VERIFY && mode == MODE_SINGLE) { 319 /* noOutputForOp = TRUE; */ 320 /* Yes, use *outLen not outLen (think in2/in2Len) */ 321 rv = FUNCLIST(fw_st_id)->C_Verify(hSession, in, 322 inLen, out, *outLen); 323 } else if (optype == CKF_VERIFY && mode == MODE_UPDATE) { 324 /* noOutputForOp = TRUE; */ 325 rv = FUNCLIST(fw_st_id)->C_VerifyUpdate(hSession, in, 326 inLen); 327 } else if (optype == CKF_VERIFY && mode == MODE_FINAL) { 328 /* noOutputForOp = TRUE; */ 329 /* Yes, use in/inLen instead of out/outLen */ 330 rv = FUNCLIST(fw_st_id)->C_VerifyFinal(hSession, in, 331 inLen); 332 333 } else if (optype == CKF_SIGN_RECOVER && mode == MODE_SINGLE) { 334 rv = FUNCLIST(fw_st_id)->C_SignRecover(hSession, in, 335 inLen, out, outLen); 336 } else if (optype == CKF_VERIFY_RECOVER && mode == MODE_SINGLE) { 337 rv = FUNCLIST(fw_st_id)->C_VerifyRecover(hSession, in, 338 inLen, out, outLen); 339 340 } else { 341 rv = CKR_FUNCTION_FAILED; 342 } 343 344 345 /* 346 * Mark the operation type as inactive if an abnormal error 347 * happens, or if the operation normally results in an inactive 348 * operation state. 349 * 350 * NOTE: The spec isn't very explicit about what happens when you 351 * call C_FooFinal (or C_Foo) with a NULL output buffer (to get the 352 * output size), but there is no output. Technically this should be 353 * no different than the normal case (ie, when there is output), and 354 * the operation should remain active until the second call actually 355 * terminates it. However, one could make the case that there is no 356 * need for a second call, since no data is available. This presents 357 * dilemma for metaslot, because we don't know if the operation is 358 * going to remain active or not. We will assume a strict reading of 359 * the spec, the operation will remain active. 360 */ 361 if (rv == CKR_BUFFER_TOO_SMALL || 362 (rv == CKR_OK && out == NULL && optype != CKF_VERIFY)) { 363 /* Leave op active for retry (with larger buffer). */ 364 shutdown = B_FALSE; 365 } else if (rv != CKR_OK) { 366 shutdown = B_TRUE; 367 finished_normally = B_FALSE; 368 } else { /* CKR_OK */ 369 if (mode == MODE_SINGLE || mode == MODE_FINAL) { 370 shutdown = B_TRUE; 371 finished_normally = B_TRUE; 372 } else { /* mode == MODE_UPDATE */ 373 shutdown = B_FALSE; 374 } 375 } 376 377 if (shutdown) 378 meta_operation_cleanup(session, optype, finished_normally); 379 380 return (rv); 381 } 382 383 /* 384 * meta_operation_cleanup 385 * 386 * Cleans up an operation in the specified session. 387 * If the operation did not finish normally, it will force 388 * the operation to terminate. 389 */ 390 void 391 meta_operation_cleanup(meta_session_t *session, CK_FLAGS optype, 392 boolean_t finished_normally) 393 { 394 operation_info_t *op; 395 CK_SESSION_HANDLE hSession; 396 CK_SLOT_ID fw_st_id; 397 398 if (!finished_normally) { 399 CK_BYTE dummy_buf[8]; 400 401 if (session->op1.type == optype) 402 op = &session->op1; 403 else 404 return; 405 406 hSession = op->session->hSession; 407 fw_st_id = op->session->fw_st_id; 408 409 /* 410 * There's no simple, reliable way to abort an 411 * operation. So, we'll force the operation to finish. 412 * 413 * We are here either because we need to abort either after 414 * C_xxxxxInit() or C_xxxxxUpdate(). 415 * 416 * We will call C_xxxxxUpdate() with invalid argument to 417 * force the operation to abort. According to the PKCS#11 418 * spec, any call to C_xxxxxUpdate() returns in an error 419 * will terminate the current operation. 420 */ 421 422 switch (optype) { 423 case CKF_ENCRYPT: 424 (void) FUNCLIST(fw_st_id)->C_EncryptUpdate(hSession, 425 NULL, 8, dummy_buf, NULL); 426 break; 427 case CKF_DECRYPT: 428 (void) FUNCLIST(fw_st_id)->C_DecryptUpdate(hSession, 429 NULL, 8, dummy_buf, NULL); 430 break; 431 case CKF_DIGEST: 432 (void) FUNCLIST(fw_st_id)->C_DigestUpdate(hSession, 433 NULL, 8); 434 break; 435 case CKF_SIGN: 436 (void) FUNCLIST(fw_st_id)->C_SignUpdate(hSession, 437 NULL, 8); 438 break; 439 case CKF_SIGN_RECOVER: 440 (void) FUNCLIST(fw_st_id)->C_SignRecover(hSession, 441 NULL, 8, dummy_buf, NULL); 442 break; 443 case CKF_VERIFY: 444 (void) FUNCLIST(fw_st_id)->C_VerifyUpdate(hSession, 445 NULL, 8); 446 break; 447 case CKF_VERIFY_RECOVER: 448 (void) FUNCLIST(fw_st_id)->C_VerifyRecover(hSession, 449 NULL, 8, dummy_buf, NULL); 450 break; 451 default: 452 /*NOTREACHED*/ 453 break; 454 } 455 meta_release_slot_session(session->op1.session); 456 session->op1.session = NULL; 457 } 458 459 session->op1.type = 0; 460 } 461 462 /* 463 * Gets the list of slots that supports the specified mechanism. 464 * 465 * If "token_only", check if the keystore slot supports the specified mech, 466 * if so, return that slot only 467 * 468 * Otherwise, get list of all slots that support the mech. 469 * 470 */ 471 static CK_RV 472 get_slotlist_for_mech(CK_MECHANISM_TYPE mech_type, 473 mech_support_info_t *mech_support_info, 474 mechinfo_t ***slots, unsigned long *slot_count, boolean_t token_only, 475 CK_MECHANISM_INFO *mech_info) 476 { 477 boolean_t mech_supported = B_FALSE; 478 CK_RV rv = CKR_OK; 479 480 if (token_only) { 481 rv = meta_mechManager_slot_supports_mech(mech_type, 482 get_keystore_slotnum(), &mech_supported, 483 &((mech_support_info->supporting_slots)[0]), B_FALSE, 484 mech_info); 485 486 if (rv != CKR_OK) { 487 return (rv); 488 } 489 490 if (mech_supported) { 491 mech_support_info->mech = mech_type; 492 /* 493 * Want to leave this at 0, that way, when 494 * other operation needs to 495 * use this mechanism, but not just for the 496 * keystore slot, we will look at other slots 497 */ 498 mech_support_info->num_supporting_slots = 0; 499 *slots = mech_support_info->supporting_slots; 500 *slot_count = 1; 501 } else { 502 rv = CKR_FUNCTION_FAILED; 503 } 504 } else { 505 /* 506 * Get a list of slots that support this mech . 507 * 508 * If the specified mechanism is used last time, 509 * the list of capable slots is already retrieved. 510 * We can save some processing, and just use that list of slots. 511 */ 512 if ((mech_support_info->mech != mech_type) || 513 (mech_support_info->num_supporting_slots == 0)) { 514 mech_support_info->mech = mech_type; 515 rv = meta_mechManager_get_slots(mech_support_info, 516 B_FALSE, mech_info); 517 if (rv != CKR_OK) { 518 return (CKR_FUNCTION_FAILED); 519 } 520 } 521 *slots = mech_support_info->supporting_slots; 522 *slot_count = mech_support_info->num_supporting_slots; 523 } 524 return (rv); 525 } 526 527 /* 528 * meta_generate_keys 529 * 530 * Generates symmetric (k1=key, k2=null) or asymmetric (k1=pub, k2=priv) keys. 531 * 532 */ 533 CK_RV 534 meta_generate_keys(meta_session_t *session, CK_MECHANISM *pMechanism, 535 CK_ATTRIBUTE *k1Template, CK_ULONG k1AttrCount, meta_object_t *key1, 536 CK_ATTRIBUTE *k2Template, CK_ULONG k2AttrCount, meta_object_t *key2) 537 { 538 CK_RV rv, save_rv; 539 slot_session_t *gen_session = NULL; 540 slot_object_t *slot_key1 = NULL, *slot_key2 = NULL; 541 mechinfo_t **slots = NULL; 542 unsigned long i, slotCount = 0; 543 boolean_t doKeyPair = B_FALSE, token_only = B_FALSE; 544 CK_ULONG slotnum; 545 CK_MECHANISM_INFO mech_info; 546 /* 547 * Since the keygen call is in a loop, it is performance-wise useful 548 * to keep track of the token value 549 */ 550 CK_BBOOL current_token1_value = FALSE, current_token2_value = FALSE; 551 552 (void) get_template_boolean(CKA_TOKEN, k1Template, k1AttrCount, 553 &(key1->isToken)); 554 (void) get_template_boolean(CKA_SENSITIVE, k1Template, k1AttrCount, 555 &(key1->isSensitive)); 556 (void) get_template_boolean(CKA_PRIVATE, k1Template, k1AttrCount, 557 &(key1->isPrivate)); 558 559 if (!get_template_boolean(CKA_EXTRACTABLE, k1Template, k1AttrCount, 560 &(key1->isExtractable))) 561 key1->isExtractable = B_TRUE; 562 563 if (key1->isToken) 564 current_token1_value = TRUE; 565 566 mech_info.flags = CKF_GENERATE; 567 568 if (key2) { 569 (void) get_template_boolean(CKA_TOKEN, k2Template, k2AttrCount, 570 &(key2->isToken)); 571 (void) get_template_boolean(CKA_SENSITIVE, k2Template, 572 k2AttrCount, &(key2->isSensitive)); 573 (void) get_template_boolean(CKA_PRIVATE, k2Template, 574 k2AttrCount, &(key2->isPrivate)); 575 576 if (!get_template_boolean(CKA_EXTRACTABLE, k2Template, 577 k2AttrCount, &(key2->isExtractable))) 578 key2->isExtractable = B_TRUE; 579 580 if (key2->isToken) 581 current_token2_value = TRUE; 582 583 doKeyPair = B_TRUE; 584 mech_info.flags = CKF_GENERATE_KEY_PAIR; 585 } 586 587 588 /* Can't create token objects in a read-only session. */ 589 if ((IS_READ_ONLY_SESSION(session->session_flags)) && 590 ((key1->isToken) || ((key2) && (key2->isToken)))) { 591 return (CKR_SESSION_READ_ONLY); 592 } 593 594 if (meta_freeobject_check(session, key1, pMechanism, k1Template, 595 k1AttrCount, NULL)) { 596 597 if ((key1->isPrivate || (doKeyPair && key2->isPrivate)) && 598 !metaslot_logged_in()) 599 return (CKR_USER_NOT_LOGGED_IN); 600 601 if (!meta_freeobject_set(key1, k1Template, k1AttrCount, 602 B_FALSE)) 603 return (CKR_FUNCTION_FAILED); 604 605 if (doKeyPair) { 606 key2->isFreeObject = FREE_ALLOWED_KEY; 607 if (!meta_freeobject_set(key2, k2Template, k2AttrCount, 608 B_FALSE)) 609 return (CKR_FUNCTION_FAILED); 610 } 611 612 } else if (doKeyPair) { 613 /* 614 * If this is a keypair operation, the second key cannot be 615 * a FreeObject if the first is not. Both keys will have the 616 * same fate when it comes to provider choices 617 */ 618 key2->isFreeObject = FREE_DISABLED; 619 key2->isFreeToken = FREE_DISABLED; 620 } 621 622 if ((key1->isToken) || ((doKeyPair) && (key2->isToken))) { 623 /* 624 * Token objects can only be generated in the token object 625 * slot. If token object slot doesn't support generating 626 * the key, it will just not be done. 627 */ 628 token_only = B_TRUE; 629 } 630 631 rv = get_slotlist_for_mech(pMechanism->mechanism, 632 &(session->mech_support_info), &slots, &slotCount, token_only, 633 &mech_info); 634 635 if (rv != CKR_OK) { 636 goto finish; 637 } 638 639 rv = meta_slot_object_alloc(&slot_key1); 640 if (doKeyPair && rv == CKR_OK) 641 rv = meta_slot_object_alloc(&slot_key2); 642 if (rv != CKR_OK) 643 goto finish; 644 645 /* Attempt to generate key on slots until one succeeds. */ 646 for (i = 0; i < slotCount; i++) { 647 CK_SESSION_HANDLE hSession; 648 CK_SLOT_ID fw_st_id; 649 650 gen_session = NULL; 651 652 slotnum = slots[i]->slotnum; 653 654 if (session->op1.session != NULL) { 655 if ((session->op1.session)->slotnum == slotnum) { 656 gen_session = session->op1.session; 657 /* 658 * set it to NULL for now, assign it to 659 * gen_session again if it is successful 660 */ 661 session->op1.session = NULL; 662 } else { 663 gen_session = NULL; 664 } 665 } 666 667 if (gen_session == NULL) { 668 rv = meta_get_slot_session(slotnum, &gen_session, 669 session->session_flags); 670 if (rv != CKR_OK) { 671 goto loop_cleanup; 672 } 673 } 674 675 /* 676 * If this is a freetoken, make sure the templates are 677 * approriate for the slot being used. 678 */ 679 if (key1->isFreeToken == FREE_ENABLED) { 680 rv = meta_freetoken_set(slotnum, 681 ¤t_token1_value, k1Template, k1AttrCount); 682 if (rv != CKR_OK) 683 goto loop_cleanup; 684 } 685 686 if (doKeyPair && key2->isFreeToken == FREE_ENABLED) { 687 rv = meta_freetoken_set(slotnum, 688 ¤t_token2_value, k2Template, k2AttrCount); 689 if (rv != CKR_OK) 690 goto loop_cleanup; 691 } 692 693 fw_st_id = gen_session->fw_st_id; 694 hSession = gen_session->hSession; 695 696 if (doKeyPair) { 697 rv = FUNCLIST(fw_st_id)->C_GenerateKeyPair(hSession, 698 pMechanism, k1Template, k1AttrCount, 699 k2Template, k2AttrCount, 700 &slot_key1->hObject, &slot_key2->hObject); 701 } else { 702 rv = FUNCLIST(fw_st_id)->C_GenerateKey(hSession, 703 pMechanism, k1Template, k1AttrCount, 704 &slot_key1->hObject); 705 } 706 707 if (rv == CKR_OK) 708 break; 709 710 loop_cleanup: 711 if (i == 0) { 712 save_rv = rv; 713 } 714 715 if (gen_session) { 716 meta_release_slot_session(gen_session); 717 gen_session = NULL; 718 } 719 } 720 if (rv != CKR_OK) { 721 rv = save_rv; 722 goto finish; 723 } 724 725 rv = meta_object_get_attr(gen_session, slot_key1->hObject, key1); 726 if (rv != CKR_OK) { 727 goto finish; 728 } 729 730 if (key2) { 731 rv = meta_object_get_attr(gen_session, slot_key2->hObject, 732 key2); 733 if (rv != CKR_OK) { 734 goto finish; 735 } 736 } 737 738 meta_slot_object_activate(slot_key1, gen_session, key1->isToken); 739 key1->clones[slotnum] = slot_key1; 740 key1->master_clone_slotnum = slotnum; 741 slot_key1 = NULL; 742 if (key1->isFreeObject == FREE_ENABLED) { 743 rv = meta_freeobject_clone(session, key1); 744 if (rv != CKR_OK) 745 goto finish; 746 } 747 748 if (doKeyPair) { 749 meta_slot_object_activate(slot_key2, gen_session, 750 key2->isToken); 751 key2->clones[slotnum] = slot_key2; 752 key2->master_clone_slotnum = slotnum; 753 slot_key2 = NULL; 754 if (key2->isFreeObject == FREE_ENABLED) { 755 rv = meta_freeobject_clone(session, key2); 756 if (rv != CKR_OK) 757 goto finish; 758 } 759 } 760 761 finish: 762 if (slot_key1) { 763 meta_slot_object_dealloc(slot_key1); 764 } 765 766 if (slot_key2) { 767 meta_slot_object_dealloc(slot_key2); 768 } 769 770 /* Save the session in case it can be used later */ 771 if (rv == CKR_OK) { 772 /* 773 * If currently stored session is not the one being in use now, 774 * release the previous one and store the current one 775 */ 776 if ((session->op1.session) && 777 (session->op1.session != gen_session)) { 778 meta_release_slot_session(session->op1.session); 779 } 780 781 /* Save the session */ 782 session->op1.session = gen_session; 783 } 784 785 return (rv); 786 } 787 788 789 /* 790 * meta_wrap_key 791 * 792 */ 793 CK_RV 794 meta_wrap_key(meta_session_t *session, CK_MECHANISM *pMechanism, 795 meta_object_t *wrappingkey, meta_object_t *inputkey, CK_BYTE *wrapped_key, 796 CK_ULONG *wrapped_key_len) 797 { 798 CK_RV rv, save_rv; 799 slot_session_t *wrap_session = NULL; 800 slot_object_t *slot_wrappingkey, *slot_inputkey; 801 mechinfo_t **slots = NULL; 802 unsigned long i, slotCount = 0; 803 CK_ULONG slotnum; 804 CK_MECHANISM_INFO mech_info; 805 806 /* 807 * If the key to be wrapped is a token object, 808 * the operation can only be done in the token object slot. 809 */ 810 mech_info.flags = CKF_WRAP; 811 rv = get_slotlist_for_mech(pMechanism->mechanism, 812 &(session->mech_support_info), &slots, &slotCount, 813 inputkey->isToken, &mech_info); 814 815 if (rv != CKR_OK) { 816 return (rv); 817 } 818 819 /* Attempt to wrap key on slots until one succeeds. */ 820 for (i = 0; i < slotCount; i++) { 821 822 slotnum = slots[i]->slotnum; 823 wrap_session = NULL; 824 825 if (session->op1.session != NULL) { 826 if ((session->op1.session)->slotnum == slotnum) { 827 wrap_session = session->op1.session; 828 /* 829 * set it to NULL for now, assign it to 830 * wrap_session again if it is successful 831 */ 832 session->op1.session = NULL; 833 } else { 834 wrap_session = NULL; 835 } 836 } 837 838 if (wrap_session == NULL) { 839 rv = meta_get_slot_session(slotnum, &wrap_session, 840 session->session_flags); 841 if (rv != CKR_OK) { 842 goto loop_cleanup; 843 } 844 } 845 846 rv = meta_object_get_clone(wrappingkey, slotnum, 847 wrap_session, &slot_wrappingkey); 848 if (rv != CKR_OK) 849 goto loop_cleanup; 850 851 rv = meta_object_get_clone(inputkey, slotnum, 852 wrap_session, &slot_inputkey); 853 if (rv != CKR_OK) 854 goto loop_cleanup; 855 856 rv = FUNCLIST(wrap_session->fw_st_id)->C_WrapKey( 857 wrap_session->hSession, pMechanism, 858 slot_wrappingkey->hObject, slot_inputkey->hObject, 859 wrapped_key, wrapped_key_len); 860 861 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 862 break; 863 864 loop_cleanup: 865 if (i == 0) { 866 save_rv = rv; 867 } 868 869 if (wrap_session) { 870 meta_release_slot_session(wrap_session); 871 wrap_session = NULL; 872 } 873 } 874 if (rv != CKR_OK) { 875 if (rv != CKR_BUFFER_TOO_SMALL) { 876 if (i == slotCount) { 877 rv = save_rv; 878 } 879 } 880 } 881 882 finish: 883 /* Save the session in case it can be used later */ 884 if (rv == CKR_OK) { 885 /* 886 * If currently stored session is not the one being in use now, 887 * release the previous one and store the current one 888 */ 889 if ((session->op1.session) && 890 (session->op1.session != wrap_session)) { 891 meta_release_slot_session(session->op1.session); 892 } 893 894 /* Save the session */ 895 session->op1.session = wrap_session; 896 } 897 return (rv); 898 } 899 900 901 902 /* 903 * meta_unwrap_key 904 * 905 */ 906 CK_RV 907 meta_unwrap_key(meta_session_t *session, 908 CK_MECHANISM *pMechanism, meta_object_t *unwrapping_key, 909 CK_BYTE *wrapped_key, CK_ULONG wrapped_key_len, 910 CK_ATTRIBUTE *template, CK_ULONG template_size, 911 meta_object_t *unwrapped_key) 912 { 913 CK_RV rv, save_rv; 914 CK_OBJECT_HANDLE hUnwrappedKey; 915 slot_session_t *unwrap_session = NULL; 916 slot_object_t *slot_unwrappingkey, *slot_unwrapped_key; 917 mechinfo_t **slots = NULL; 918 unsigned long i, slotCount = 0; 919 CK_ULONG slotnum; 920 CK_MECHANISM_INFO mech_info; 921 922 /* Can't create token objects in a read-only session. */ 923 if ((IS_READ_ONLY_SESSION(session->session_flags)) && 924 unwrapped_key->isToken) { 925 return (CKR_SESSION_READ_ONLY); 926 } 927 928 /* 929 * If the the resulting unwrapped key 930 * needs to be a token object, the operation can only 931 * be performed in the token slot, if it is supported. 932 */ 933 mech_info.flags = CKF_UNWRAP; 934 rv = get_slotlist_for_mech(pMechanism->mechanism, 935 &(session->mech_support_info), &slots, &slotCount, 936 unwrapped_key->isToken, &mech_info); 937 938 if (rv != CKR_OK) { 939 return (rv); 940 } 941 942 rv = meta_slot_object_alloc(&slot_unwrapped_key); 943 if (rv != CKR_OK) { 944 goto finish; 945 } 946 947 /* Attempt to unwrap key on slots until one succeeds. */ 948 for (i = 0; i < slotCount; i++) { 949 950 slotnum = slots[i]->slotnum; 951 unwrap_session = NULL; 952 953 if (session->op1.session != NULL) { 954 if ((session->op1.session)->slotnum == slotnum) { 955 unwrap_session = session->op1.session; 956 /* 957 * set it to NULL for now, assign it to 958 * unwrap_session again if it is successful 959 */ 960 session->op1.session = NULL; 961 } else { 962 unwrap_session = NULL; 963 } 964 } 965 966 if (unwrap_session == NULL) { 967 rv = meta_get_slot_session(slotnum, &unwrap_session, 968 session->session_flags); 969 if (rv != CKR_OK) { 970 goto loop_cleanup; 971 } 972 } 973 974 rv = meta_object_get_clone(unwrapping_key, slotnum, 975 unwrap_session, &slot_unwrappingkey); 976 if (rv != CKR_OK) 977 goto loop_cleanup; 978 979 rv = FUNCLIST(unwrap_session->fw_st_id)->C_UnwrapKey( 980 unwrap_session->hSession, pMechanism, 981 slot_unwrappingkey->hObject, wrapped_key, wrapped_key_len, 982 template, template_size, &hUnwrappedKey); 983 984 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 985 break; 986 loop_cleanup: 987 if (i == 0) { 988 save_rv = rv; 989 } 990 991 if (unwrap_session) { 992 meta_release_slot_session(unwrap_session); 993 unwrap_session = NULL; 994 } 995 } 996 997 998 if (rv != CKR_OK) { 999 if (rv != CKR_BUFFER_TOO_SMALL) { 1000 rv = save_rv; 1001 } 1002 goto finish; 1003 } 1004 1005 1006 slot_unwrapped_key->hObject = hUnwrappedKey; 1007 unwrapped_key->clones[slotnum] = slot_unwrapped_key; 1008 unwrapped_key->master_clone_slotnum = slotnum; 1009 rv = meta_object_get_attr(unwrap_session, 1010 slot_unwrapped_key->hObject, unwrapped_key); 1011 if (rv != CKR_OK) { 1012 goto finish; 1013 } 1014 meta_slot_object_activate(slot_unwrapped_key, unwrap_session, 1015 unwrapped_key->isToken); 1016 slot_unwrapped_key = NULL; 1017 1018 finish: 1019 if (slot_unwrapped_key) { 1020 meta_slot_object_dealloc(slot_unwrapped_key); 1021 } 1022 1023 /* Save the session in case it can be used later */ 1024 if (rv == CKR_OK) { 1025 /* 1026 * If currently stored session is not the one being in use now, 1027 * release the previous one and store the current one 1028 */ 1029 if ((session->op1.session) && 1030 (session->op1.session != unwrap_session)) { 1031 meta_release_slot_session(session->op1.session); 1032 } 1033 1034 /* Save the session */ 1035 session->op1.session = unwrap_session; 1036 } 1037 1038 return (rv); 1039 } 1040 1041 1042 /* 1043 * meta_derive_key 1044 * 1045 * Core implementation for C_DeriveKey. This function is a bit gross because 1046 * of PKCS#11 kludges that pass extra object handles in the mechanism 1047 * parameters. Normally C_DeriveKey takes a single existing key as input, 1048 * and creates a single new key as output. But a few mechanisms take 2 keys 1049 * as input, and the two SSL/TLS mechanisms create 4 keys as output. 1050 * 1051 * When an extra input key (basekey2) is set, we set *phBaseKey2 to the clone's 1052 * object handle. phBaseKey2 is provided by the caller so we don't have to 1053 * trudge down into different mechanism parameters to set it when issuing the 1054 * operation. 1055 * 1056 * For the SSL/TLS mechanisms, newKey2/newKey3/newKey4 will be set. We pull 1057 * the new handles from pMech->pParameter in order to fill in the appropriate 1058 * meta_object fields. 1059 */ 1060 CK_RV 1061 meta_derive_key(meta_session_t *session, CK_MECHANISM *pMechanism, 1062 meta_object_t *basekey1, meta_object_t *basekey2, 1063 CK_OBJECT_HANDLE *phBaseKey2, 1064 CK_ATTRIBUTE *pTemplate, CK_ULONG ulAttributeCount, 1065 meta_object_t *newKey1, meta_object_t *newKey2, 1066 meta_object_t *newKey3, meta_object_t *newKey4) 1067 { 1068 CK_RV rv, save_rv; 1069 CK_OBJECT_HANDLE hDerivedKey; 1070 1071 CK_ULONG slotnum; 1072 boolean_t isSSL = B_FALSE; 1073 boolean_t isTLSPRF = B_FALSE; 1074 mechinfo_t **slots = NULL; 1075 unsigned long i, slot_count = 0; 1076 slot_session_t *derive_session = NULL; 1077 slot_object_t *slot_basekey1 = NULL, *slot_basekey2 = NULL; 1078 slot_object_t *slotkey1 = NULL, *slotkey2 = NULL, *slotkey3 = NULL, 1079 *slotkey4 = NULL; 1080 CK_MECHANISM_INFO mech_info; 1081 CK_BBOOL current_token_value = FALSE; 1082 1083 /* 1084 * if the derived key needs to be a token object, can only 1085 * perform the derive operation in the token slot 1086 */ 1087 (void) get_template_boolean(CKA_TOKEN, pTemplate, ulAttributeCount, 1088 &(newKey1->isToken)); 1089 (void) get_template_boolean(CKA_PRIVATE, pTemplate, ulAttributeCount, 1090 &(newKey1->isPrivate)); 1091 (void) get_template_boolean(CKA_SENSITIVE, pTemplate, ulAttributeCount, 1092 &(newKey1->isSensitive)); 1093 1094 if (newKey1->isToken) 1095 current_token_value = TRUE; 1096 1097 /* Can't create token objects in a read-only session. */ 1098 if ((IS_READ_ONLY_SESSION(session->session_flags)) && 1099 newKey1->isToken) { 1100 rv = CKR_SESSION_READ_ONLY; 1101 goto finish; 1102 } 1103 1104 if (meta_freeobject_check(session, newKey1, pMechanism, pTemplate, 1105 ulAttributeCount, NULL)) { 1106 1107 if (newKey1->isPrivate && !metaslot_logged_in()) 1108 return (CKR_USER_NOT_LOGGED_IN); 1109 1110 if (!meta_freeobject_set(newKey1, pTemplate, ulAttributeCount, 1111 B_FALSE)) 1112 return (CKR_FUNCTION_FAILED); 1113 } 1114 1115 mech_info.flags = CKF_DERIVE; 1116 rv = get_slotlist_for_mech(pMechanism->mechanism, 1117 &(session->mech_support_info), &slots, &slot_count, 1118 newKey1->isToken, &mech_info); 1119 1120 if (rv != CKR_OK) { 1121 return (rv); 1122 } 1123 1124 if (pMechanism->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE || 1125 pMechanism->mechanism == CKM_TLS_KEY_AND_MAC_DERIVE) 1126 isSSL = B_TRUE; 1127 1128 else if (pMechanism->mechanism == CKM_TLS_PRF) 1129 isTLSPRF = B_TRUE; 1130 1131 rv = meta_slot_object_alloc(&slotkey1); 1132 if (isSSL) { 1133 if (rv == CKR_OK) 1134 rv = meta_slot_object_alloc(&slotkey2); 1135 if (rv == CKR_OK) 1136 rv = meta_slot_object_alloc(&slotkey3); 1137 if (rv == CKR_OK) 1138 rv = meta_slot_object_alloc(&slotkey4); 1139 } 1140 if (rv != CKR_OK) { 1141 goto finish; 1142 } 1143 1144 for (i = 0; i < slot_count; i++) { 1145 slotnum = slots[i]->slotnum; 1146 1147 derive_session = NULL; 1148 1149 if (session->op1.session != NULL) { 1150 if ((session->op1.session)->slotnum == slotnum) { 1151 derive_session = session->op1.session; 1152 /* 1153 * set it to NULL for now, assign it to 1154 * derive_session again if it is successful 1155 */ 1156 session->op1.session = NULL; 1157 } else { 1158 derive_session = NULL; 1159 } 1160 } 1161 1162 if (derive_session == NULL) { 1163 rv = meta_get_slot_session(slotnum, &derive_session, 1164 session->session_flags); 1165 if (rv != CKR_OK) { 1166 goto loop_cleanup; 1167 } 1168 } 1169 1170 rv = meta_object_get_clone(basekey1, slotnum, 1171 derive_session, &slot_basekey1); 1172 if (rv != CKR_OK) 1173 goto loop_cleanup; 1174 1175 if (basekey2) { 1176 rv = meta_object_get_clone(basekey2, slotnum, 1177 derive_session, &slot_basekey2); 1178 if (rv != CKR_OK) 1179 goto loop_cleanup; 1180 1181 /* Pass the handle somewhere in the mech params. */ 1182 *phBaseKey2 = slot_basekey2->hObject; 1183 } 1184 1185 if (newKey1->isFreeToken == FREE_ENABLED) { 1186 rv = meta_freetoken_set(slotnum, ¤t_token_value, 1187 pTemplate, ulAttributeCount); 1188 if (rv != CKR_OK) 1189 goto loop_cleanup; 1190 } 1191 1192 rv = FUNCLIST(derive_session->fw_st_id)->C_DeriveKey( 1193 derive_session->hSession, pMechanism, 1194 slot_basekey1->hObject, pTemplate, ulAttributeCount, 1195 (isSSL || isTLSPRF) ? NULL : &hDerivedKey); 1196 1197 if (rv == CKR_OK) 1198 break; 1199 loop_cleanup: 1200 if (i == 0) { 1201 save_rv = rv; 1202 } 1203 1204 if (derive_session) { 1205 meta_release_slot_session(derive_session); 1206 derive_session = NULL; 1207 } 1208 /* No need to cleanup clones, so we can reuse them later. */ 1209 } 1210 1211 if (rv != CKR_OK) { 1212 rv = save_rv; 1213 goto finish; 1214 } 1215 1216 if (isTLSPRF) 1217 goto finish; 1218 1219 /* 1220 * These SSL/TLS are unique in that the parameter in the API for 1221 * the new key is unused (NULL). Instead, there are 4 keys which 1222 * are derived, and are passed back through the mechanism params. 1223 * Both mechs use the same mechanism parameter type. 1224 */ 1225 if (isSSL) { 1226 CK_SSL3_KEY_MAT_PARAMS *keyparams; 1227 CK_SSL3_KEY_MAT_OUT *keys; 1228 1229 /* NULL checks already done by caller */ 1230 keyparams = (CK_SSL3_KEY_MAT_PARAMS*)pMechanism->pParameter; 1231 keys = keyparams->pReturnedKeyMaterial; 1232 1233 slotkey1->hObject = keys->hClientMacSecret; 1234 slotkey2->hObject = keys->hServerMacSecret; 1235 slotkey3->hObject = keys->hClientKey; 1236 slotkey4->hObject = keys->hServerKey; 1237 1238 rv = meta_object_get_attr(derive_session, 1239 slotkey1->hObject, newKey1); 1240 if (rv != CKR_OK) { 1241 goto finish; 1242 } 1243 1244 rv = meta_object_get_attr(derive_session, 1245 slotkey2->hObject, newKey2); 1246 if (rv != CKR_OK) { 1247 goto finish; 1248 } 1249 1250 rv = meta_object_get_attr(derive_session, 1251 slotkey3->hObject, newKey3); 1252 if (rv != CKR_OK) { 1253 goto finish; 1254 } 1255 1256 rv = meta_object_get_attr(derive_session, 1257 slotkey4->hObject, newKey4); 1258 if (rv != CKR_OK) { 1259 goto finish; 1260 } 1261 1262 newKey1->clones[slotnum] = slotkey1; 1263 newKey2->clones[slotnum] = slotkey2; 1264 newKey3->clones[slotnum] = slotkey3; 1265 newKey4->clones[slotnum] = slotkey4; 1266 1267 newKey1->master_clone_slotnum = slotnum; 1268 newKey2->master_clone_slotnum = slotnum; 1269 newKey3->master_clone_slotnum = slotnum; 1270 newKey4->master_clone_slotnum = slotnum; 1271 1272 meta_slot_object_activate(slotkey1, derive_session, 1273 newKey1->isToken); 1274 slotkey1 = NULL; 1275 meta_slot_object_activate(slotkey2, derive_session, 1276 newKey2->isToken); 1277 slotkey2 = NULL; 1278 meta_slot_object_activate(slotkey3, derive_session, 1279 newKey3->isToken); 1280 slotkey3 = NULL; 1281 meta_slot_object_activate(slotkey4, derive_session, 1282 newKey4->isToken); 1283 slotkey4 = NULL; 1284 1285 } else { 1286 slotkey1->hObject = hDerivedKey; 1287 newKey1->clones[slotnum] = slotkey1; 1288 newKey1->master_clone_slotnum = slotnum; 1289 1290 rv = meta_object_get_attr(derive_session, 1291 slotkey1->hObject, newKey1); 1292 if (rv != CKR_OK) { 1293 goto finish; 1294 } 1295 1296 meta_slot_object_activate(slotkey1, derive_session, 1297 newKey1->isToken); 1298 slotkey1 = NULL; 1299 } 1300 1301 if (newKey1->isFreeObject == FREE_ENABLED) 1302 (void) meta_freeobject_clone(session, newKey1); 1303 1304 1305 finish: 1306 if (slotkey1) { 1307 meta_slot_object_dealloc(slotkey1); 1308 } 1309 if (slotkey2) { 1310 meta_slot_object_dealloc(slotkey2); 1311 } 1312 if (slotkey3) { 1313 meta_slot_object_dealloc(slotkey3); 1314 } 1315 if (slotkey4) { 1316 meta_slot_object_dealloc(slotkey4); 1317 } 1318 1319 /* Save the session in case it can be used later */ 1320 if (rv == CKR_OK) { 1321 /* 1322 * If currently stored session is not the one being in use now, 1323 * release the previous one and store the current one 1324 */ 1325 if ((session->op1.session) && 1326 (session->op1.session != derive_session)) { 1327 meta_release_slot_session(session->op1.session); 1328 } 1329 1330 /* Save the session */ 1331 session->op1.session = derive_session; 1332 } 1333 1334 return (rv); 1335 } 1336 1337 1338 /* 1339 * Check the following 4 environment variables for user/application's 1340 * configuration for metaslot. User's configuration takes precedence 1341 * over the system wide configuration for metaslot 1342 * 1343 * ${METASLOT_ENABLED} 1344 * ${METASLOT_OBJECTSTORE_SLOT} 1345 * ${METASLOT_OBJECTSTORE_TOKEN} 1346 * ${METASLOT_AUTO_KEY_MIGRATE} 1347 * 1348 * values defined in these environment variables will be stored in the 1349 * global variable "metaslot_config" 1350 */ 1351 void 1352 get_user_metaslot_config() 1353 { 1354 char *env_val = NULL; 1355 1356 /* 1357 * Check to see if any environment variable is defined 1358 * by the user for configuring metaslot. 1359 */ 1360 bzero(&metaslot_config, sizeof (metaslot_config)); 1361 1362 /* METASLOT_ENABLED */ 1363 env_val = getenv("METASLOT_ENABLED"); 1364 if (env_val) { 1365 metaslot_config.enabled_specified = B_TRUE; 1366 if (strcasecmp(env_val, TRUE_STRING) == 0) { 1367 metaslot_config.enabled = B_TRUE; 1368 } else if (strcasecmp(env_val, FALSE_STRING) == 0) { 1369 metaslot_config.enabled = B_FALSE; 1370 } else { 1371 /* value is neither 1 or 0, ignore this value */ 1372 metaslot_config.enabled_specified = B_FALSE; 1373 } 1374 } 1375 1376 /* METASLOT_AUTO_KEY_MIGRATE */ 1377 env_val = getenv("METASLOT_AUTO_KEY_MIGRATE"); 1378 if (env_val) { 1379 metaslot_config.auto_key_migrate_specified = B_TRUE; 1380 if (strcasecmp(env_val, TRUE_STRING) == 0) { 1381 metaslot_config.auto_key_migrate = B_TRUE; 1382 } else if (strcasecmp(env_val, FALSE_STRING) == 0) { 1383 metaslot_config.auto_key_migrate = B_FALSE; 1384 } else { 1385 /* value is neither 1 or 0, ignore this value */ 1386 metaslot_config.auto_key_migrate_specified = B_FALSE; 1387 } 1388 } 1389 1390 /* METASLOT_OBJECTSTORE_SLOT */ 1391 env_val = getenv("METASLOT_OBJECTSTORE_SLOT"); 1392 if (env_val) { 1393 metaslot_config.keystore_slot_specified = B_TRUE; 1394 (void) strlcpy((char *)metaslot_config.keystore_slot, env_val, 1395 SLOT_DESCRIPTION_SIZE); 1396 } 1397 1398 /* METASLOT_OBJECTSTORE_TOKEN */ 1399 env_val = getenv("METASLOT_OBJECTSTORE_TOKEN"); 1400 if (env_val) { 1401 metaslot_config.keystore_token_specified = B_TRUE; 1402 (void) strlcpy((char *)metaslot_config.keystore_token, env_val, 1403 TOKEN_LABEL_SIZE); 1404 } 1405 } 1406