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