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