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 } 686 free(session->init.pMech); 687 session->init.pMech = NULL; 688 } 689 } 690 691 /* 692 * meta_operation_cleanup 693 * 694 * Cleans up an operation in the specified session. 695 * If the operation did not finish normally, it will force 696 * the operation to terminate. 697 */ 698 void 699 meta_operation_cleanup(meta_session_t *session, CK_FLAGS optype, 700 boolean_t finished_normally) 701 { 702 operation_info_t *op; 703 CK_SESSION_HANDLE hSession; 704 CK_SLOT_ID fw_st_id; 705 706 if (!finished_normally) { 707 CK_BYTE dummy_buf[8]; 708 709 if (session->op1.type == optype) { 710 op = &session->op1; 711 } else { 712 if ((optype == CKF_ENCRYPT) || 713 (optype == CKF_DECRYPT) || 714 (optype == CKF_DIGEST)) { 715 session->op1.type = 0; 716 session->init.app = B_FALSE; 717 session->init.done = B_FALSE; 718 free_session_mechanism(session); 719 } 720 return; 721 } 722 723 hSession = op->session->hSession; 724 fw_st_id = op->session->fw_st_id; 725 726 /* 727 * There's no simple, reliable way to abort an 728 * operation. So, we'll force the operation to finish. 729 * 730 * We are here either because we need to abort either after 731 * C_xxxxxInit() or C_xxxxxUpdate(). 732 * 733 * We will call C_xxxxxUpdate() with invalid argument to 734 * force the operation to abort. According to the PKCS#11 735 * spec, any call to C_xxxxxUpdate() returns in an error 736 * will terminate the current operation. 737 */ 738 739 switch (optype) { 740 case CKF_ENCRYPT: 741 (void) FUNCLIST(fw_st_id)->C_EncryptUpdate(hSession, 742 NULL, 8, dummy_buf, NULL); 743 break; 744 case CKF_DECRYPT: 745 (void) FUNCLIST(fw_st_id)->C_DecryptUpdate(hSession, 746 NULL, 8, dummy_buf, NULL); 747 break; 748 case CKF_DIGEST: 749 (void) FUNCLIST(fw_st_id)->C_DigestUpdate(hSession, 750 NULL, 8); 751 break; 752 case CKF_SIGN: 753 (void) FUNCLIST(fw_st_id)->C_SignUpdate(hSession, 754 NULL, 8); 755 break; 756 case CKF_SIGN_RECOVER: 757 (void) FUNCLIST(fw_st_id)->C_SignRecover(hSession, 758 NULL, 8, dummy_buf, NULL); 759 break; 760 case CKF_VERIFY: 761 (void) FUNCLIST(fw_st_id)->C_VerifyUpdate(hSession, 762 NULL, 8); 763 break; 764 case CKF_VERIFY_RECOVER: 765 (void) FUNCLIST(fw_st_id)->C_VerifyRecover(hSession, 766 NULL, 8, dummy_buf, NULL); 767 break; 768 default: 769 /*NOTREACHED*/ 770 break; 771 } 772 meta_release_slot_session(session->op1.session); 773 session->op1.session = NULL; 774 } 775 776 if ((optype == CKF_ENCRYPT) || (optype == CKF_DECRYPT) || 777 (optype == CKF_DIGEST)) { 778 session->init.done = B_FALSE; 779 free_session_mechanism(session); 780 } 781 session->op1.type = 0; 782 } 783 784 /* 785 * Gets the list of slots that supports the specified mechanism. 786 * 787 * If "token_only", check if the keystore slot supports the specified mech, 788 * if so, return that slot only 789 * 790 * Otherwise, get list of all slots that support the mech. 791 * 792 */ 793 static CK_RV 794 get_slotlist_for_mech(CK_MECHANISM_TYPE mech_type, 795 mech_support_info_t *mech_support_info, 796 mechinfo_t ***slots, unsigned long *slot_count, boolean_t token_only, 797 CK_MECHANISM_INFO *mech_info) 798 { 799 boolean_t mech_supported = B_FALSE; 800 CK_RV rv = CKR_OK; 801 802 if (token_only) { 803 rv = meta_mechManager_slot_supports_mech(mech_type, 804 get_keystore_slotnum(), &mech_supported, 805 &((mech_support_info->supporting_slots)[0]), B_FALSE, 806 mech_info); 807 808 if (rv != CKR_OK) { 809 return (rv); 810 } 811 812 if (mech_supported) { 813 mech_support_info->mech = mech_type; 814 /* 815 * Want to leave this at 0, that way, when 816 * other operation needs to 817 * use this mechanism, but not just for the 818 * keystore slot, we will look at other slots 819 */ 820 mech_support_info->num_supporting_slots = 0; 821 *slots = mech_support_info->supporting_slots; 822 *slot_count = 1; 823 } else { 824 rv = CKR_FUNCTION_FAILED; 825 } 826 } else { 827 /* 828 * Get a list of slots that support this mech . 829 * 830 * If the specified mechanism is used last time, 831 * the list of capable slots is already retrieved. 832 * We can save some processing, and just use that list of slots. 833 */ 834 if ((mech_support_info->mech != mech_type) || 835 (mech_support_info->num_supporting_slots == 0)) { 836 mech_support_info->mech = mech_type; 837 rv = meta_mechManager_get_slots(mech_support_info, 838 B_FALSE, mech_info); 839 if (rv != CKR_OK) { 840 return (CKR_FUNCTION_FAILED); 841 } 842 } 843 *slots = mech_support_info->supporting_slots; 844 *slot_count = mech_support_info->num_supporting_slots; 845 } 846 return (rv); 847 } 848 849 /* 850 * meta_generate_keys 851 * 852 * Generates symmetric (k1=key, k2=null) or asymmetric (k1=pub, k2=priv) keys. 853 * 854 */ 855 CK_RV 856 meta_generate_keys(meta_session_t *session, CK_MECHANISM *pMechanism, 857 CK_ATTRIBUTE *k1Template, CK_ULONG k1AttrCount, meta_object_t *key1, 858 CK_ATTRIBUTE *k2Template, CK_ULONG k2AttrCount, meta_object_t *key2) 859 { 860 CK_RV rv, save_rv; 861 slot_session_t *gen_session = NULL; 862 slot_object_t *slot_key1 = NULL, *slot_key2 = NULL; 863 mechinfo_t **slots = NULL; 864 unsigned long i, slotCount = 0; 865 boolean_t doKeyPair = B_FALSE, token_only = B_FALSE; 866 CK_ULONG slotnum; 867 CK_MECHANISM_INFO mech_info; 868 /* 869 * Since the keygen call is in a loop, it is performance-wise useful 870 * to keep track of the token value 871 */ 872 CK_BBOOL current_token1_value = FALSE, current_token2_value = FALSE; 873 874 (void) get_template_boolean(CKA_TOKEN, k1Template, k1AttrCount, 875 &(key1->isToken)); 876 (void) get_template_boolean(CKA_SENSITIVE, k1Template, k1AttrCount, 877 &(key1->isSensitive)); 878 (void) get_template_boolean(CKA_PRIVATE, k1Template, k1AttrCount, 879 &(key1->isPrivate)); 880 881 if (!get_template_boolean(CKA_EXTRACTABLE, k1Template, k1AttrCount, 882 &(key1->isExtractable))) 883 key1->isExtractable = B_TRUE; 884 885 if (key1->isToken) 886 current_token1_value = TRUE; 887 888 mech_info.flags = CKF_GENERATE; 889 890 if (key2) { 891 (void) get_template_boolean(CKA_TOKEN, k2Template, k2AttrCount, 892 &(key2->isToken)); 893 (void) get_template_boolean(CKA_SENSITIVE, k2Template, 894 k2AttrCount, &(key2->isSensitive)); 895 (void) get_template_boolean(CKA_PRIVATE, k2Template, 896 k2AttrCount, &(key2->isPrivate)); 897 898 if (!get_template_boolean(CKA_EXTRACTABLE, k2Template, 899 k2AttrCount, &(key2->isExtractable))) 900 key2->isExtractable = B_TRUE; 901 902 if (key2->isToken) 903 current_token2_value = TRUE; 904 905 doKeyPair = B_TRUE; 906 mech_info.flags = CKF_GENERATE_KEY_PAIR; 907 } 908 909 910 /* Can't create token objects in a read-only session. */ 911 if ((IS_READ_ONLY_SESSION(session->session_flags)) && 912 ((key1->isToken) || ((key2) && (key2->isToken)))) { 913 return (CKR_SESSION_READ_ONLY); 914 } 915 916 if (meta_freeobject_check(session, key1, pMechanism, k1Template, 917 k1AttrCount, NULL)) { 918 919 if ((key1->isPrivate || (doKeyPair && key2->isPrivate)) && 920 !metaslot_logged_in()) 921 return (CKR_USER_NOT_LOGGED_IN); 922 923 if (!meta_freeobject_set(key1, k1Template, k1AttrCount, 924 B_FALSE)) 925 return (CKR_FUNCTION_FAILED); 926 927 if (doKeyPair) { 928 key2->isFreeObject = FREE_ALLOWED_KEY; 929 if (!meta_freeobject_set(key2, k2Template, k2AttrCount, 930 B_FALSE)) 931 return (CKR_FUNCTION_FAILED); 932 } 933 934 } else if (doKeyPair) { 935 /* 936 * If this is a keypair operation, the second key cannot be 937 * a FreeObject if the first is not. Both keys will have the 938 * same fate when it comes to provider choices 939 */ 940 key2->isFreeObject = FREE_DISABLED; 941 key2->isFreeToken = FREE_DISABLED; 942 } 943 944 if ((key1->isToken) || ((doKeyPair) && (key2->isToken))) { 945 /* 946 * Token objects can only be generated in the token object 947 * slot. If token object slot doesn't support generating 948 * the key, it will just not be done. 949 */ 950 token_only = B_TRUE; 951 } 952 953 rv = get_slotlist_for_mech(pMechanism->mechanism, 954 &(session->mech_support_info), &slots, &slotCount, token_only, 955 &mech_info); 956 957 if (rv != CKR_OK) { 958 goto finish; 959 } 960 961 rv = meta_slot_object_alloc(&slot_key1); 962 if (doKeyPair && rv == CKR_OK) 963 rv = meta_slot_object_alloc(&slot_key2); 964 if (rv != CKR_OK) 965 goto finish; 966 967 /* Attempt to generate key on slots until one succeeds. */ 968 for (i = 0; i < slotCount; i++) { 969 CK_SESSION_HANDLE hSession; 970 CK_SLOT_ID fw_st_id; 971 972 gen_session = NULL; 973 974 slotnum = slots[i]->slotnum; 975 976 if (session->op1.session != NULL) { 977 if ((session->op1.session)->slotnum == slotnum) { 978 gen_session = session->op1.session; 979 /* 980 * set it to NULL for now, assign it to 981 * gen_session again if it is successful 982 */ 983 session->op1.session = NULL; 984 } else { 985 gen_session = NULL; 986 } 987 } 988 989 if (gen_session == NULL) { 990 rv = meta_get_slot_session(slotnum, &gen_session, 991 session->session_flags); 992 if (rv != CKR_OK) { 993 goto loop_cleanup; 994 } 995 } 996 997 /* 998 * If this is a freetoken, make sure the templates are 999 * approriate for the slot being used. 1000 */ 1001 if (key1->isFreeToken == FREE_ENABLED) { 1002 rv = meta_freetoken_set(slotnum, 1003 ¤t_token1_value, k1Template, k1AttrCount); 1004 if (rv != CKR_OK) 1005 goto loop_cleanup; 1006 } 1007 1008 if (doKeyPair && key2->isFreeToken == FREE_ENABLED) { 1009 rv = meta_freetoken_set(slotnum, 1010 ¤t_token2_value, k2Template, k2AttrCount); 1011 if (rv != CKR_OK) 1012 goto loop_cleanup; 1013 } 1014 1015 fw_st_id = gen_session->fw_st_id; 1016 hSession = gen_session->hSession; 1017 1018 if (doKeyPair) { 1019 rv = FUNCLIST(fw_st_id)->C_GenerateKeyPair(hSession, 1020 pMechanism, k1Template, k1AttrCount, 1021 k2Template, k2AttrCount, 1022 &slot_key1->hObject, &slot_key2->hObject); 1023 } else { 1024 rv = FUNCLIST(fw_st_id)->C_GenerateKey(hSession, 1025 pMechanism, k1Template, k1AttrCount, 1026 &slot_key1->hObject); 1027 } 1028 1029 if (rv == CKR_OK) 1030 break; 1031 1032 loop_cleanup: 1033 if (i == 0) { 1034 save_rv = rv; 1035 } 1036 1037 if (gen_session) { 1038 meta_release_slot_session(gen_session); 1039 gen_session = NULL; 1040 } 1041 } 1042 if (rv != CKR_OK) { 1043 rv = save_rv; 1044 goto finish; 1045 } 1046 1047 rv = meta_object_get_attr(gen_session, slot_key1->hObject, key1); 1048 if (rv != CKR_OK) { 1049 goto finish; 1050 } 1051 1052 if (key2) { 1053 rv = meta_object_get_attr(gen_session, slot_key2->hObject, 1054 key2); 1055 if (rv != CKR_OK) { 1056 goto finish; 1057 } 1058 } 1059 1060 meta_slot_object_activate(slot_key1, gen_session, key1->isToken); 1061 key1->clones[slotnum] = slot_key1; 1062 key1->master_clone_slotnum = slotnum; 1063 slot_key1 = NULL; 1064 if (key1->isFreeObject == FREE_ENABLED) { 1065 rv = meta_freeobject_clone(session, key1); 1066 if (rv != CKR_OK) 1067 goto finish; 1068 } 1069 1070 if (doKeyPair) { 1071 meta_slot_object_activate(slot_key2, gen_session, 1072 key2->isToken); 1073 key2->clones[slotnum] = slot_key2; 1074 key2->master_clone_slotnum = slotnum; 1075 slot_key2 = NULL; 1076 if (key2->isFreeObject == FREE_ENABLED) { 1077 rv = meta_freeobject_clone(session, key2); 1078 if (rv != CKR_OK) 1079 goto finish; 1080 } 1081 } 1082 1083 finish: 1084 if (slot_key1) { 1085 meta_slot_object_dealloc(slot_key1); 1086 } 1087 1088 if (slot_key2) { 1089 meta_slot_object_dealloc(slot_key2); 1090 } 1091 1092 /* Save the session in case it can be used later */ 1093 if (rv == CKR_OK) { 1094 /* 1095 * If currently stored session is not the one being in use now, 1096 * release the previous one and store the current one 1097 */ 1098 if ((session->op1.session) && 1099 (session->op1.session != gen_session)) { 1100 meta_release_slot_session(session->op1.session); 1101 } 1102 1103 /* Save the session */ 1104 session->op1.session = gen_session; 1105 } 1106 1107 return (rv); 1108 } 1109 1110 1111 /* 1112 * meta_wrap_key 1113 * 1114 */ 1115 CK_RV 1116 meta_wrap_key(meta_session_t *session, CK_MECHANISM *pMechanism, 1117 meta_object_t *wrappingkey, meta_object_t *inputkey, CK_BYTE *wrapped_key, 1118 CK_ULONG *wrapped_key_len) 1119 { 1120 CK_RV rv, save_rv; 1121 slot_session_t *wrap_session = NULL; 1122 slot_object_t *slot_wrappingkey, *slot_inputkey; 1123 mechinfo_t **slots = NULL; 1124 unsigned long i, slotCount = 0; 1125 CK_ULONG slotnum; 1126 CK_MECHANISM_INFO mech_info; 1127 1128 /* 1129 * If the key to be wrapped is a token object, 1130 * the operation can only be done in the token object slot. 1131 */ 1132 mech_info.flags = CKF_WRAP; 1133 rv = get_slotlist_for_mech(pMechanism->mechanism, 1134 &(session->mech_support_info), &slots, &slotCount, 1135 inputkey->isToken, &mech_info); 1136 1137 if (rv != CKR_OK) { 1138 return (rv); 1139 } 1140 1141 /* Attempt to wrap key on slots until one succeeds. */ 1142 for (i = 0; i < slotCount; i++) { 1143 1144 slotnum = slots[i]->slotnum; 1145 wrap_session = NULL; 1146 1147 if (session->op1.session != NULL) { 1148 if ((session->op1.session)->slotnum == slotnum) { 1149 wrap_session = session->op1.session; 1150 /* 1151 * set it to NULL for now, assign it to 1152 * wrap_session again if it is successful 1153 */ 1154 session->op1.session = NULL; 1155 } else { 1156 wrap_session = NULL; 1157 } 1158 } 1159 1160 if (wrap_session == NULL) { 1161 rv = meta_get_slot_session(slotnum, &wrap_session, 1162 session->session_flags); 1163 if (rv != CKR_OK) { 1164 goto loop_cleanup; 1165 } 1166 } 1167 1168 rv = meta_object_get_clone(wrappingkey, slotnum, 1169 wrap_session, &slot_wrappingkey); 1170 if (rv != CKR_OK) 1171 goto loop_cleanup; 1172 1173 rv = meta_object_get_clone(inputkey, slotnum, 1174 wrap_session, &slot_inputkey); 1175 if (rv != CKR_OK) 1176 goto loop_cleanup; 1177 1178 rv = FUNCLIST(wrap_session->fw_st_id)->C_WrapKey( 1179 wrap_session->hSession, pMechanism, 1180 slot_wrappingkey->hObject, slot_inputkey->hObject, 1181 wrapped_key, wrapped_key_len); 1182 1183 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 1184 break; 1185 1186 loop_cleanup: 1187 if (i == 0) { 1188 save_rv = rv; 1189 } 1190 1191 if (wrap_session) { 1192 meta_release_slot_session(wrap_session); 1193 wrap_session = NULL; 1194 } 1195 } 1196 if (rv != CKR_OK) { 1197 if (rv != CKR_BUFFER_TOO_SMALL) { 1198 if (i == slotCount) { 1199 rv = save_rv; 1200 } 1201 } 1202 } 1203 1204 finish: 1205 /* Save the session in case it can be used later */ 1206 if (rv == CKR_OK) { 1207 /* 1208 * If currently stored session is not the one being in use now, 1209 * release the previous one and store the current one 1210 */ 1211 if ((session->op1.session) && 1212 (session->op1.session != wrap_session)) { 1213 meta_release_slot_session(session->op1.session); 1214 } 1215 1216 /* Save the session */ 1217 session->op1.session = wrap_session; 1218 } 1219 return (rv); 1220 } 1221 1222 1223 1224 /* 1225 * meta_unwrap_key 1226 * 1227 */ 1228 CK_RV 1229 meta_unwrap_key(meta_session_t *session, 1230 CK_MECHANISM *pMechanism, meta_object_t *unwrapping_key, 1231 CK_BYTE *wrapped_key, CK_ULONG wrapped_key_len, 1232 CK_ATTRIBUTE *template, CK_ULONG template_size, 1233 meta_object_t *unwrapped_key) 1234 { 1235 CK_RV rv, save_rv; 1236 CK_OBJECT_HANDLE hUnwrappedKey; 1237 slot_session_t *unwrap_session = NULL; 1238 slot_object_t *slot_unwrappingkey, *slot_unwrapped_key; 1239 mechinfo_t **slots = NULL; 1240 unsigned long i, slotCount = 0; 1241 CK_ULONG slotnum; 1242 CK_MECHANISM_INFO mech_info; 1243 1244 /* Can't create token objects in a read-only session. */ 1245 if ((IS_READ_ONLY_SESSION(session->session_flags)) && 1246 unwrapped_key->isToken) { 1247 return (CKR_SESSION_READ_ONLY); 1248 } 1249 1250 /* 1251 * If the the resulting unwrapped key 1252 * needs to be a token object, the operation can only 1253 * be performed in the token slot, if it is supported. 1254 */ 1255 mech_info.flags = CKF_UNWRAP; 1256 rv = get_slotlist_for_mech(pMechanism->mechanism, 1257 &(session->mech_support_info), &slots, &slotCount, 1258 unwrapped_key->isToken, &mech_info); 1259 1260 if (rv != CKR_OK) { 1261 return (rv); 1262 } 1263 1264 rv = meta_slot_object_alloc(&slot_unwrapped_key); 1265 if (rv != CKR_OK) { 1266 goto finish; 1267 } 1268 1269 /* Attempt to unwrap key on slots until one succeeds. */ 1270 for (i = 0; i < slotCount; i++) { 1271 1272 slotnum = slots[i]->slotnum; 1273 unwrap_session = NULL; 1274 1275 if (session->op1.session != NULL) { 1276 if ((session->op1.session)->slotnum == slotnum) { 1277 unwrap_session = session->op1.session; 1278 /* 1279 * set it to NULL for now, assign it to 1280 * unwrap_session again if it is successful 1281 */ 1282 session->op1.session = NULL; 1283 } else { 1284 unwrap_session = NULL; 1285 } 1286 } 1287 1288 if (unwrap_session == NULL) { 1289 rv = meta_get_slot_session(slotnum, &unwrap_session, 1290 session->session_flags); 1291 if (rv != CKR_OK) { 1292 goto loop_cleanup; 1293 } 1294 } 1295 1296 rv = meta_object_get_clone(unwrapping_key, slotnum, 1297 unwrap_session, &slot_unwrappingkey); 1298 if (rv != CKR_OK) 1299 goto loop_cleanup; 1300 1301 rv = FUNCLIST(unwrap_session->fw_st_id)->C_UnwrapKey( 1302 unwrap_session->hSession, pMechanism, 1303 slot_unwrappingkey->hObject, wrapped_key, wrapped_key_len, 1304 template, template_size, &hUnwrappedKey); 1305 1306 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 1307 break; 1308 loop_cleanup: 1309 if (i == 0) { 1310 save_rv = rv; 1311 } 1312 1313 if (unwrap_session) { 1314 meta_release_slot_session(unwrap_session); 1315 unwrap_session = NULL; 1316 } 1317 } 1318 1319 1320 if (rv != CKR_OK) { 1321 if (rv != CKR_BUFFER_TOO_SMALL) { 1322 rv = save_rv; 1323 } 1324 goto finish; 1325 } 1326 1327 1328 slot_unwrapped_key->hObject = hUnwrappedKey; 1329 unwrapped_key->clones[slotnum] = slot_unwrapped_key; 1330 unwrapped_key->master_clone_slotnum = slotnum; 1331 rv = meta_object_get_attr(unwrap_session, 1332 slot_unwrapped_key->hObject, unwrapped_key); 1333 if (rv != CKR_OK) { 1334 goto finish; 1335 } 1336 meta_slot_object_activate(slot_unwrapped_key, unwrap_session, 1337 unwrapped_key->isToken); 1338 slot_unwrapped_key = NULL; 1339 1340 finish: 1341 if (slot_unwrapped_key) { 1342 meta_slot_object_dealloc(slot_unwrapped_key); 1343 } 1344 1345 /* Save the session in case it can be used later */ 1346 if (rv == CKR_OK) { 1347 /* 1348 * If currently stored session is not the one being in use now, 1349 * release the previous one and store the current one 1350 */ 1351 if ((session->op1.session) && 1352 (session->op1.session != unwrap_session)) { 1353 meta_release_slot_session(session->op1.session); 1354 } 1355 1356 /* Save the session */ 1357 session->op1.session = unwrap_session; 1358 } 1359 1360 return (rv); 1361 } 1362 1363 1364 /* 1365 * meta_derive_key 1366 * 1367 * Core implementation for C_DeriveKey. This function is a bit gross because 1368 * of PKCS#11 kludges that pass extra object handles in the mechanism 1369 * parameters. Normally C_DeriveKey takes a single existing key as input, 1370 * and creates a single new key as output. But a few mechanisms take 2 keys 1371 * as input, and the two SSL/TLS mechanisms create 4 keys as output. 1372 * 1373 * When an extra input key (basekey2) is set, we set *phBaseKey2 to the clone's 1374 * object handle. phBaseKey2 is provided by the caller so we don't have to 1375 * trudge down into different mechanism parameters to set it when issuing the 1376 * operation. 1377 * 1378 * For the SSL/TLS mechanisms, newKey2/newKey3/newKey4 will be set. We pull 1379 * the new handles from pMech->pParameter in order to fill in the appropriate 1380 * meta_object fields. 1381 */ 1382 CK_RV 1383 meta_derive_key(meta_session_t *session, CK_MECHANISM *pMechanism, 1384 meta_object_t *basekey1, meta_object_t *basekey2, 1385 CK_OBJECT_HANDLE *phBaseKey2, 1386 CK_ATTRIBUTE *pTemplate, CK_ULONG ulAttributeCount, 1387 meta_object_t *newKey1, meta_object_t *newKey2, 1388 meta_object_t *newKey3, meta_object_t *newKey4) 1389 { 1390 CK_RV rv, save_rv; 1391 CK_OBJECT_HANDLE hDerivedKey; 1392 1393 CK_ULONG slotnum; 1394 boolean_t isSSL = B_FALSE; 1395 boolean_t isTLSPRF = B_FALSE; 1396 mechinfo_t **slots = NULL; 1397 unsigned long i, slot_count = 0; 1398 slot_session_t *derive_session = NULL; 1399 slot_object_t *slot_basekey1 = NULL, *slot_basekey2 = NULL; 1400 slot_object_t *slotkey1 = NULL, *slotkey2 = NULL, *slotkey3 = NULL, 1401 *slotkey4 = NULL; 1402 CK_MECHANISM_INFO mech_info; 1403 CK_BBOOL current_token_value = FALSE; 1404 1405 /* 1406 * if the derived key needs to be a token object, can only 1407 * perform the derive operation in the token slot 1408 */ 1409 (void) get_template_boolean(CKA_TOKEN, pTemplate, ulAttributeCount, 1410 &(newKey1->isToken)); 1411 (void) get_template_boolean(CKA_PRIVATE, pTemplate, ulAttributeCount, 1412 &(newKey1->isPrivate)); 1413 (void) get_template_boolean(CKA_SENSITIVE, pTemplate, ulAttributeCount, 1414 &(newKey1->isSensitive)); 1415 1416 if (newKey1->isToken) 1417 current_token_value = TRUE; 1418 1419 /* Can't create token objects in a read-only session. */ 1420 if ((IS_READ_ONLY_SESSION(session->session_flags)) && 1421 newKey1->isToken) { 1422 rv = CKR_SESSION_READ_ONLY; 1423 goto finish; 1424 } 1425 1426 if (meta_freeobject_check(session, newKey1, pMechanism, pTemplate, 1427 ulAttributeCount, NULL)) { 1428 1429 if (newKey1->isPrivate && !metaslot_logged_in()) 1430 return (CKR_USER_NOT_LOGGED_IN); 1431 1432 if (!meta_freeobject_set(newKey1, pTemplate, ulAttributeCount, 1433 B_FALSE)) 1434 return (CKR_FUNCTION_FAILED); 1435 } 1436 1437 mech_info.flags = CKF_DERIVE; 1438 rv = get_slotlist_for_mech(pMechanism->mechanism, 1439 &(session->mech_support_info), &slots, &slot_count, 1440 newKey1->isToken, &mech_info); 1441 1442 if (rv != CKR_OK) { 1443 return (rv); 1444 } 1445 1446 if (pMechanism->mechanism == CKM_SSL3_KEY_AND_MAC_DERIVE || 1447 pMechanism->mechanism == CKM_TLS_KEY_AND_MAC_DERIVE) 1448 isSSL = B_TRUE; 1449 1450 else if (pMechanism->mechanism == CKM_TLS_PRF) 1451 isTLSPRF = B_TRUE; 1452 1453 rv = meta_slot_object_alloc(&slotkey1); 1454 if (isSSL) { 1455 if (rv == CKR_OK) 1456 rv = meta_slot_object_alloc(&slotkey2); 1457 if (rv == CKR_OK) 1458 rv = meta_slot_object_alloc(&slotkey3); 1459 if (rv == CKR_OK) 1460 rv = meta_slot_object_alloc(&slotkey4); 1461 } 1462 if (rv != CKR_OK) { 1463 goto finish; 1464 } 1465 1466 for (i = 0; i < slot_count; i++) { 1467 slotnum = slots[i]->slotnum; 1468 1469 derive_session = NULL; 1470 1471 if (session->op1.session != NULL) { 1472 if ((session->op1.session)->slotnum == slotnum) { 1473 derive_session = session->op1.session; 1474 /* 1475 * set it to NULL for now, assign it to 1476 * derive_session again if it is successful 1477 */ 1478 session->op1.session = NULL; 1479 } else { 1480 derive_session = NULL; 1481 } 1482 } 1483 1484 if (derive_session == NULL) { 1485 rv = meta_get_slot_session(slotnum, &derive_session, 1486 session->session_flags); 1487 if (rv != CKR_OK) { 1488 goto loop_cleanup; 1489 } 1490 } 1491 1492 rv = meta_object_get_clone(basekey1, slotnum, 1493 derive_session, &slot_basekey1); 1494 if (rv != CKR_OK) 1495 goto loop_cleanup; 1496 1497 if (basekey2) { 1498 rv = meta_object_get_clone(basekey2, slotnum, 1499 derive_session, &slot_basekey2); 1500 if (rv != CKR_OK) 1501 goto loop_cleanup; 1502 1503 /* Pass the handle somewhere in the mech params. */ 1504 *phBaseKey2 = slot_basekey2->hObject; 1505 } 1506 1507 if (newKey1->isFreeToken == FREE_ENABLED) { 1508 rv = meta_freetoken_set(slotnum, ¤t_token_value, 1509 pTemplate, ulAttributeCount); 1510 if (rv != CKR_OK) 1511 goto loop_cleanup; 1512 } 1513 1514 rv = FUNCLIST(derive_session->fw_st_id)->C_DeriveKey( 1515 derive_session->hSession, pMechanism, 1516 slot_basekey1->hObject, pTemplate, ulAttributeCount, 1517 (isSSL || isTLSPRF) ? NULL : &hDerivedKey); 1518 1519 if (rv == CKR_OK) 1520 break; 1521 loop_cleanup: 1522 if (i == 0) { 1523 save_rv = rv; 1524 } 1525 1526 if (derive_session) { 1527 meta_release_slot_session(derive_session); 1528 derive_session = NULL; 1529 } 1530 /* No need to cleanup clones, so we can reuse them later. */ 1531 } 1532 1533 if (rv != CKR_OK) { 1534 rv = save_rv; 1535 goto finish; 1536 } 1537 1538 if (isTLSPRF) 1539 goto finish; 1540 1541 /* 1542 * These SSL/TLS are unique in that the parameter in the API for 1543 * the new key is unused (NULL). Instead, there are 4 keys which 1544 * are derived, and are passed back through the mechanism params. 1545 * Both mechs use the same mechanism parameter type. 1546 */ 1547 if (isSSL) { 1548 CK_SSL3_KEY_MAT_PARAMS *keyparams; 1549 CK_SSL3_KEY_MAT_OUT *keys; 1550 1551 /* NULL checks already done by caller */ 1552 keyparams = (CK_SSL3_KEY_MAT_PARAMS*)pMechanism->pParameter; 1553 keys = keyparams->pReturnedKeyMaterial; 1554 1555 slotkey1->hObject = keys->hClientMacSecret; 1556 slotkey2->hObject = keys->hServerMacSecret; 1557 slotkey3->hObject = keys->hClientKey; 1558 slotkey4->hObject = keys->hServerKey; 1559 1560 rv = meta_object_get_attr(derive_session, 1561 slotkey1->hObject, newKey1); 1562 if (rv != CKR_OK) { 1563 goto finish; 1564 } 1565 1566 rv = meta_object_get_attr(derive_session, 1567 slotkey2->hObject, newKey2); 1568 if (rv != CKR_OK) { 1569 goto finish; 1570 } 1571 1572 rv = meta_object_get_attr(derive_session, 1573 slotkey3->hObject, newKey3); 1574 if (rv != CKR_OK) { 1575 goto finish; 1576 } 1577 1578 rv = meta_object_get_attr(derive_session, 1579 slotkey4->hObject, newKey4); 1580 if (rv != CKR_OK) { 1581 goto finish; 1582 } 1583 1584 newKey1->clones[slotnum] = slotkey1; 1585 newKey2->clones[slotnum] = slotkey2; 1586 newKey3->clones[slotnum] = slotkey3; 1587 newKey4->clones[slotnum] = slotkey4; 1588 1589 newKey1->master_clone_slotnum = slotnum; 1590 newKey2->master_clone_slotnum = slotnum; 1591 newKey3->master_clone_slotnum = slotnum; 1592 newKey4->master_clone_slotnum = slotnum; 1593 1594 meta_slot_object_activate(slotkey1, derive_session, 1595 newKey1->isToken); 1596 slotkey1 = NULL; 1597 meta_slot_object_activate(slotkey2, derive_session, 1598 newKey2->isToken); 1599 slotkey2 = NULL; 1600 meta_slot_object_activate(slotkey3, derive_session, 1601 newKey3->isToken); 1602 slotkey3 = NULL; 1603 meta_slot_object_activate(slotkey4, derive_session, 1604 newKey4->isToken); 1605 slotkey4 = NULL; 1606 1607 } else { 1608 slotkey1->hObject = hDerivedKey; 1609 newKey1->clones[slotnum] = slotkey1; 1610 newKey1->master_clone_slotnum = slotnum; 1611 1612 rv = meta_object_get_attr(derive_session, 1613 slotkey1->hObject, newKey1); 1614 if (rv != CKR_OK) { 1615 goto finish; 1616 } 1617 1618 meta_slot_object_activate(slotkey1, derive_session, 1619 newKey1->isToken); 1620 slotkey1 = NULL; 1621 } 1622 1623 if (newKey1->isFreeObject == FREE_ENABLED) 1624 (void) meta_freeobject_clone(session, newKey1); 1625 1626 1627 finish: 1628 if (slotkey1) { 1629 meta_slot_object_dealloc(slotkey1); 1630 } 1631 if (slotkey2) { 1632 meta_slot_object_dealloc(slotkey2); 1633 } 1634 if (slotkey3) { 1635 meta_slot_object_dealloc(slotkey3); 1636 } 1637 if (slotkey4) { 1638 meta_slot_object_dealloc(slotkey4); 1639 } 1640 1641 /* Save the session in case it can be used later */ 1642 if (rv == CKR_OK) { 1643 /* 1644 * If currently stored session is not the one being in use now, 1645 * release the previous one and store the current one 1646 */ 1647 if ((session->op1.session) && 1648 (session->op1.session != derive_session)) { 1649 meta_release_slot_session(session->op1.session); 1650 } 1651 1652 /* Save the session */ 1653 session->op1.session = derive_session; 1654 } 1655 1656 return (rv); 1657 } 1658 1659 1660 /* 1661 * Check the following 4 environment variables for user/application's 1662 * configuration for metaslot. User's configuration takes precedence 1663 * over the system wide configuration for metaslot 1664 * 1665 * ${METASLOT_ENABLED} 1666 * ${METASLOT_OBJECTSTORE_SLOT} 1667 * ${METASLOT_OBJECTSTORE_TOKEN} 1668 * ${METASLOT_AUTO_KEY_MIGRATE} 1669 * 1670 * values defined in these environment variables will be stored in the 1671 * global variable "metaslot_config" 1672 */ 1673 void 1674 get_user_metaslot_config() 1675 { 1676 char *env_val = NULL; 1677 1678 /* 1679 * Check to see if any environment variable is defined 1680 * by the user for configuring metaslot. 1681 */ 1682 bzero(&metaslot_config, sizeof (metaslot_config)); 1683 1684 /* METASLOT_ENABLED */ 1685 env_val = getenv("METASLOT_ENABLED"); 1686 if (env_val) { 1687 metaslot_config.enabled_specified = B_TRUE; 1688 if (strcasecmp(env_val, TRUE_STRING) == 0) { 1689 metaslot_config.enabled = B_TRUE; 1690 } else if (strcasecmp(env_val, FALSE_STRING) == 0) { 1691 metaslot_config.enabled = B_FALSE; 1692 } else { 1693 /* value is neither 1 or 0, ignore this value */ 1694 metaslot_config.enabled_specified = B_FALSE; 1695 } 1696 } 1697 1698 /* METASLOT_AUTO_KEY_MIGRATE */ 1699 env_val = getenv("METASLOT_AUTO_KEY_MIGRATE"); 1700 if (env_val) { 1701 metaslot_config.auto_key_migrate_specified = B_TRUE; 1702 if (strcasecmp(env_val, TRUE_STRING) == 0) { 1703 metaslot_config.auto_key_migrate = B_TRUE; 1704 } else if (strcasecmp(env_val, FALSE_STRING) == 0) { 1705 metaslot_config.auto_key_migrate = B_FALSE; 1706 } else { 1707 /* value is neither 1 or 0, ignore this value */ 1708 metaslot_config.auto_key_migrate_specified = B_FALSE; 1709 } 1710 } 1711 1712 /* METASLOT_OBJECTSTORE_SLOT */ 1713 env_val = getenv("METASLOT_OBJECTSTORE_SLOT"); 1714 if (env_val) { 1715 metaslot_config.keystore_slot_specified = B_TRUE; 1716 (void) strlcpy((char *)metaslot_config.keystore_slot, env_val, 1717 SLOT_DESCRIPTION_SIZE); 1718 } 1719 1720 /* METASLOT_OBJECTSTORE_TOKEN */ 1721 env_val = getenv("METASLOT_OBJECTSTORE_TOKEN"); 1722 if (env_val) { 1723 metaslot_config.keystore_token_specified = B_TRUE; 1724 (void) strlcpy((char *)metaslot_config.keystore_token, env_val, 1725 TOKEN_LABEL_SIZE); 1726 } 1727 } 1728