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