session.c (62399B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* 6 * session.c 7 * 8 * This file implements the NSSCKFWSession type and methods. 9 */ 10 11 #ifndef CK_T 12 #include "ck.h" 13 #endif /* CK_T */ 14 15 /* 16 * NSSCKFWSession 17 * 18 * -- create/destroy -- 19 * nssCKFWSession_Create 20 * nssCKFWSession_Destroy 21 * 22 * -- public accessors -- 23 * NSSCKFWSession_GetMDSession 24 * NSSCKFWSession_GetArena 25 * NSSCKFWSession_CallNotification 26 * NSSCKFWSession_IsRWSession 27 * NSSCKFWSession_IsSO 28 * NSSCKFWSession_GetFWSlot 29 * 30 * -- implement public accessors -- 31 * nssCKFWSession_GetMDSession 32 * nssCKFWSession_GetArena 33 * nssCKFWSession_CallNotification 34 * nssCKFWSession_IsRWSession 35 * nssCKFWSession_IsSO 36 * nssCKFWSession_GetFWSlot 37 * 38 * -- private accessors -- 39 * nssCKFWSession_GetSessionState 40 * nssCKFWSession_SetFWFindObjects 41 * nssCKFWSession_GetFWFindObjects 42 * nssCKFWSession_SetMDSession 43 * nssCKFWSession_SetHandle 44 * nssCKFWSession_GetHandle 45 * nssCKFWSession_RegisterSessionObject 46 * nssCKFWSession_DeegisterSessionObject 47 * 48 * -- module fronts -- 49 * nssCKFWSession_GetDeviceError 50 * nssCKFWSession_Login 51 * nssCKFWSession_Logout 52 * nssCKFWSession_InitPIN 53 * nssCKFWSession_SetPIN 54 * nssCKFWSession_GetOperationStateLen 55 * nssCKFWSession_GetOperationState 56 * nssCKFWSession_SetOperationState 57 * nssCKFWSession_CreateObject 58 * nssCKFWSession_CopyObject 59 * nssCKFWSession_FindObjectsInit 60 * nssCKFWSession_SeedRandom 61 * nssCKFWSession_GetRandom 62 */ 63 64 struct NSSCKFWSessionStr { 65 NSSArena *arena; 66 NSSCKMDSession *mdSession; 67 NSSCKFWToken *fwToken; 68 NSSCKMDToken *mdToken; 69 NSSCKFWInstance *fwInstance; 70 NSSCKMDInstance *mdInstance; 71 CK_VOID_PTR pApplication; 72 CK_NOTIFY Notify; 73 74 /* 75 * Everything above is set at creation time, and then not modified. 76 * The items below are atomic. No locking required. If we fear 77 * about pointer-copies being nonatomic, we'll lock fwFindObjects. 78 */ 79 80 CK_BBOOL rw; 81 NSSCKFWFindObjects *fwFindObjects; 82 NSSCKFWCryptoOperation *fwOperationArray[NSSCKFWCryptoOperationState_Max]; 83 nssCKFWHash *sessionObjectHash; 84 CK_SESSION_HANDLE hSession; 85 }; 86 87 #ifdef DEBUG 88 /* 89 * But first, the pointer-tracking stuff. 90 * 91 * NOTE: the pointer-tracking support in NSS/base currently relies 92 * upon NSPR's CallOnce support. That, however, relies upon NSPR's 93 * locking, which is tied into the runtime. We need a pointer-tracker 94 * implementation that uses the locks supplied through C_Initialize. 95 * That support, however, can be filled in later. So for now, I'll 96 * just do this routines as no-ops. 97 */ 98 99 static CK_RV 100 session_add_pointer( 101 const NSSCKFWSession *fwSession) 102 { 103 return CKR_OK; 104 } 105 106 static CK_RV 107 session_remove_pointer( 108 const NSSCKFWSession *fwSession) 109 { 110 return CKR_OK; 111 } 112 113 NSS_IMPLEMENT CK_RV 114 nssCKFWSession_verifyPointer( 115 const NSSCKFWSession *fwSession) 116 { 117 return CKR_OK; 118 } 119 120 #endif /* DEBUG */ 121 122 /* 123 * nssCKFWSession_Create 124 * 125 */ 126 NSS_IMPLEMENT NSSCKFWSession * 127 nssCKFWSession_Create( 128 NSSCKFWToken *fwToken, 129 CK_BBOOL rw, 130 CK_VOID_PTR pApplication, 131 CK_NOTIFY Notify, 132 CK_RV *pError) 133 { 134 NSSArena *arena = (NSSArena *)NULL; 135 NSSCKFWSession *fwSession; 136 NSSCKFWSlot *fwSlot; 137 138 #ifdef NSSDEBUG 139 if (!pError) { 140 return (NSSCKFWSession *)NULL; 141 } 142 143 *pError = nssCKFWToken_verifyPointer(fwToken); 144 if (CKR_OK != *pError) { 145 return (NSSCKFWSession *)NULL; 146 } 147 #endif /* NSSDEBUG */ 148 149 arena = NSSArena_Create(); 150 if (!arena) { 151 *pError = CKR_HOST_MEMORY; 152 return (NSSCKFWSession *)NULL; 153 } 154 155 fwSession = nss_ZNEW(arena, NSSCKFWSession); 156 if (!fwSession) { 157 *pError = CKR_HOST_MEMORY; 158 goto loser; 159 } 160 161 fwSession->arena = arena; 162 fwSession->mdSession = (NSSCKMDSession *)NULL; /* set later */ 163 fwSession->fwToken = fwToken; 164 fwSession->mdToken = nssCKFWToken_GetMDToken(fwToken); 165 166 fwSlot = nssCKFWToken_GetFWSlot(fwToken); 167 fwSession->fwInstance = nssCKFWSlot_GetFWInstance(fwSlot); 168 fwSession->mdInstance = nssCKFWSlot_GetMDInstance(fwSlot); 169 170 fwSession->rw = rw; 171 fwSession->pApplication = pApplication; 172 fwSession->Notify = Notify; 173 174 fwSession->fwFindObjects = (NSSCKFWFindObjects *)NULL; 175 176 fwSession->sessionObjectHash = nssCKFWHash_Create(fwSession->fwInstance, arena, pError); 177 if (!fwSession->sessionObjectHash) { 178 if (CKR_OK == *pError) { 179 *pError = CKR_GENERAL_ERROR; 180 } 181 goto loser; 182 } 183 184 #ifdef DEBUG 185 *pError = session_add_pointer(fwSession); 186 if (CKR_OK != *pError) { 187 goto loser; 188 } 189 #endif /* DEBUG */ 190 191 return fwSession; 192 193 loser: 194 if (arena) { 195 if (fwSession && fwSession->sessionObjectHash) { 196 (void)nssCKFWHash_Destroy(fwSession->sessionObjectHash); 197 } 198 NSSArena_Destroy(arena); 199 } 200 201 return (NSSCKFWSession *)NULL; 202 } 203 204 static void 205 nss_ckfw_session_object_destroy_iterator( 206 const void *key, 207 void *value, 208 void *closure) 209 { 210 NSSCKFWObject *fwObject = (NSSCKFWObject *)value; 211 nssCKFWObject_Finalize(fwObject, PR_TRUE); 212 } 213 214 /* 215 * nssCKFWSession_Destroy 216 * 217 */ 218 NSS_IMPLEMENT CK_RV 219 nssCKFWSession_Destroy( 220 NSSCKFWSession *fwSession, 221 CK_BBOOL removeFromTokenHash) 222 { 223 CK_RV error = CKR_OK; 224 nssCKFWHash *sessionObjectHash; 225 NSSCKFWCryptoOperationState i; 226 227 #ifdef NSSDEBUG 228 error = nssCKFWSession_verifyPointer(fwSession); 229 if (CKR_OK != error) { 230 return error; 231 } 232 #endif /* NSSDEBUG */ 233 234 if (removeFromTokenHash) { 235 error = nssCKFWToken_RemoveSession(fwSession->fwToken, fwSession); 236 } 237 238 /* 239 * Invalidate session objects 240 */ 241 242 sessionObjectHash = fwSession->sessionObjectHash; 243 fwSession->sessionObjectHash = (nssCKFWHash *)NULL; 244 245 nssCKFWHash_Iterate(sessionObjectHash, 246 nss_ckfw_session_object_destroy_iterator, 247 (void *)NULL); 248 249 for (i = 0; i < NSSCKFWCryptoOperationState_Max; i++) { 250 if (fwSession->fwOperationArray[i]) { 251 nssCKFWCryptoOperation_Destroy(fwSession->fwOperationArray[i]); 252 } 253 } 254 255 #ifdef DEBUG 256 (void)session_remove_pointer(fwSession); 257 #endif /* DEBUG */ 258 (void)nssCKFWHash_Destroy(sessionObjectHash); 259 NSSArena_Destroy(fwSession->arena); 260 261 return error; 262 } 263 264 /* 265 * nssCKFWSession_GetMDSession 266 * 267 */ 268 NSS_IMPLEMENT NSSCKMDSession * 269 nssCKFWSession_GetMDSession( 270 NSSCKFWSession *fwSession) 271 { 272 #ifdef NSSDEBUG 273 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 274 return (NSSCKMDSession *)NULL; 275 } 276 #endif /* NSSDEBUG */ 277 278 return fwSession->mdSession; 279 } 280 281 /* 282 * nssCKFWSession_GetArena 283 * 284 */ 285 NSS_IMPLEMENT NSSArena * 286 nssCKFWSession_GetArena( 287 NSSCKFWSession *fwSession, 288 CK_RV *pError) 289 { 290 #ifdef NSSDEBUG 291 if (!pError) { 292 return (NSSArena *)NULL; 293 } 294 295 *pError = nssCKFWSession_verifyPointer(fwSession); 296 if (CKR_OK != *pError) { 297 return (NSSArena *)NULL; 298 } 299 #endif /* NSSDEBUG */ 300 301 return fwSession->arena; 302 } 303 304 /* 305 * nssCKFWSession_CallNotification 306 * 307 */ 308 NSS_IMPLEMENT CK_RV 309 nssCKFWSession_CallNotification( 310 NSSCKFWSession *fwSession, 311 CK_NOTIFICATION event) 312 { 313 CK_RV error = CKR_OK; 314 CK_SESSION_HANDLE handle; 315 316 #ifdef NSSDEBUG 317 error = nssCKFWSession_verifyPointer(fwSession); 318 if (CKR_OK != error) { 319 return error; 320 } 321 #endif /* NSSDEBUG */ 322 323 if ((CK_NOTIFY)NULL == fwSession->Notify) { 324 return CKR_OK; 325 } 326 327 handle = nssCKFWInstance_FindSessionHandle(fwSession->fwInstance, fwSession); 328 if ((CK_SESSION_HANDLE)0 == handle) { 329 return CKR_GENERAL_ERROR; 330 } 331 332 error = fwSession->Notify(handle, event, fwSession->pApplication); 333 334 return error; 335 } 336 337 /* 338 * nssCKFWSession_IsRWSession 339 * 340 */ 341 NSS_IMPLEMENT CK_BBOOL 342 nssCKFWSession_IsRWSession( 343 NSSCKFWSession *fwSession) 344 { 345 #ifdef NSSDEBUG 346 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 347 return CK_FALSE; 348 } 349 #endif /* NSSDEBUG */ 350 351 return fwSession->rw; 352 } 353 354 /* 355 * nssCKFWSession_IsSO 356 * 357 */ 358 NSS_IMPLEMENT CK_BBOOL 359 nssCKFWSession_IsSO( 360 NSSCKFWSession *fwSession) 361 { 362 CK_STATE state; 363 364 #ifdef NSSDEBUG 365 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 366 return CK_FALSE; 367 } 368 #endif /* NSSDEBUG */ 369 370 state = nssCKFWToken_GetSessionState(fwSession->fwToken); 371 switch (state) { 372 case CKS_RO_PUBLIC_SESSION: 373 case CKS_RO_USER_FUNCTIONS: 374 case CKS_RW_PUBLIC_SESSION: 375 case CKS_RW_USER_FUNCTIONS: 376 return CK_FALSE; 377 case CKS_RW_SO_FUNCTIONS: 378 return CK_TRUE; 379 default: 380 return CK_FALSE; 381 } 382 } 383 384 /* 385 * nssCKFWSession_GetFWSlot 386 * 387 */ 388 NSS_IMPLEMENT NSSCKFWSlot * 389 nssCKFWSession_GetFWSlot( 390 NSSCKFWSession *fwSession) 391 { 392 #ifdef NSSDEBUG 393 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 394 return (NSSCKFWSlot *)NULL; 395 } 396 #endif /* NSSDEBUG */ 397 398 return nssCKFWToken_GetFWSlot(fwSession->fwToken); 399 } 400 401 /* 402 * nssCFKWSession_GetSessionState 403 * 404 */ 405 NSS_IMPLEMENT CK_STATE 406 nssCKFWSession_GetSessionState( 407 NSSCKFWSession *fwSession) 408 { 409 #ifdef NSSDEBUG 410 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 411 return CKS_RO_PUBLIC_SESSION; /* whatever */ 412 } 413 #endif /* NSSDEBUG */ 414 415 return nssCKFWToken_GetSessionState(fwSession->fwToken); 416 } 417 418 /* 419 * nssCKFWSession_SetFWFindObjects 420 * 421 */ 422 NSS_IMPLEMENT CK_RV 423 nssCKFWSession_SetFWFindObjects( 424 NSSCKFWSession *fwSession, 425 NSSCKFWFindObjects *fwFindObjects) 426 { 427 #ifdef NSSDEBUG 428 CK_RV error = CKR_OK; 429 #endif /* NSSDEBUG */ 430 431 #ifdef NSSDEBUG 432 error = nssCKFWSession_verifyPointer(fwSession); 433 if (CKR_OK != error) { 434 return error; 435 } 436 437 /* fwFindObjects may be null */ 438 #endif /* NSSDEBUG */ 439 440 if ((fwSession->fwFindObjects) && 441 (fwFindObjects)) { 442 return CKR_OPERATION_ACTIVE; 443 } 444 445 fwSession->fwFindObjects = fwFindObjects; 446 447 return CKR_OK; 448 } 449 450 /* 451 * nssCKFWSession_GetFWFindObjects 452 * 453 */ 454 NSS_IMPLEMENT NSSCKFWFindObjects * 455 nssCKFWSession_GetFWFindObjects( 456 NSSCKFWSession *fwSession, 457 CK_RV *pError) 458 { 459 #ifdef NSSDEBUG 460 if (!pError) { 461 return (NSSCKFWFindObjects *)NULL; 462 } 463 464 *pError = nssCKFWSession_verifyPointer(fwSession); 465 if (CKR_OK != *pError) { 466 return (NSSCKFWFindObjects *)NULL; 467 } 468 #endif /* NSSDEBUG */ 469 470 if (!fwSession->fwFindObjects) { 471 *pError = CKR_OPERATION_NOT_INITIALIZED; 472 return (NSSCKFWFindObjects *)NULL; 473 } 474 475 return fwSession->fwFindObjects; 476 } 477 478 /* 479 * nssCKFWSession_SetMDSession 480 * 481 */ 482 NSS_IMPLEMENT CK_RV 483 nssCKFWSession_SetMDSession( 484 NSSCKFWSession *fwSession, 485 NSSCKMDSession *mdSession) 486 { 487 #ifdef NSSDEBUG 488 CK_RV error = CKR_OK; 489 #endif /* NSSDEBUG */ 490 491 #ifdef NSSDEBUG 492 error = nssCKFWSession_verifyPointer(fwSession); 493 if (CKR_OK != error) { 494 return error; 495 } 496 497 if (!mdSession) { 498 return CKR_ARGUMENTS_BAD; 499 } 500 #endif /* NSSDEBUG */ 501 502 if (fwSession->mdSession) { 503 return CKR_GENERAL_ERROR; 504 } 505 506 fwSession->mdSession = mdSession; 507 508 return CKR_OK; 509 } 510 511 /* 512 * nssCKFWSession_SetHandle 513 * 514 */ 515 NSS_IMPLEMENT CK_RV 516 nssCKFWSession_SetHandle( 517 NSSCKFWSession *fwSession, 518 CK_SESSION_HANDLE hSession) 519 { 520 #ifdef NSSDEBUG 521 CK_RV error = CKR_OK; 522 #endif /* NSSDEBUG */ 523 524 #ifdef NSSDEBUG 525 error = nssCKFWSession_verifyPointer(fwSession); 526 if (CKR_OK != error) { 527 return error; 528 } 529 #endif /* NSSDEBUG */ 530 531 if ((CK_SESSION_HANDLE)0 != fwSession->hSession) { 532 return CKR_GENERAL_ERROR; 533 } 534 535 fwSession->hSession = hSession; 536 537 return CKR_OK; 538 } 539 540 /* 541 * nssCKFWSession_GetHandle 542 * 543 */ 544 NSS_IMPLEMENT CK_SESSION_HANDLE 545 nssCKFWSession_GetHandle( 546 NSSCKFWSession *fwSession) 547 { 548 #ifdef NSSDEBUG 549 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 550 return NULL; 551 } 552 #endif /* NSSDEBUG */ 553 554 return fwSession->hSession; 555 } 556 557 /* 558 * nssCKFWSession_RegisterSessionObject 559 * 560 */ 561 NSS_IMPLEMENT CK_RV 562 nssCKFWSession_RegisterSessionObject( 563 NSSCKFWSession *fwSession, 564 NSSCKFWObject *fwObject) 565 { 566 CK_RV rv = CKR_OK; 567 568 #ifdef NSSDEBUG 569 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 570 return CKR_GENERAL_ERROR; 571 } 572 #endif /* NSSDEBUG */ 573 574 if (fwSession->sessionObjectHash) { 575 rv = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject); 576 } 577 578 return rv; 579 } 580 581 /* 582 * nssCKFWSession_DeregisterSessionObject 583 * 584 */ 585 NSS_IMPLEMENT CK_RV 586 nssCKFWSession_DeregisterSessionObject( 587 NSSCKFWSession *fwSession, 588 NSSCKFWObject *fwObject) 589 { 590 #ifdef NSSDEBUG 591 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 592 return CKR_GENERAL_ERROR; 593 } 594 #endif /* NSSDEBUG */ 595 596 if (fwSession->sessionObjectHash) { 597 nssCKFWHash_Remove(fwSession->sessionObjectHash, fwObject); 598 } 599 600 return CKR_OK; 601 } 602 603 /* 604 * nssCKFWSession_GetDeviceError 605 * 606 */ 607 NSS_IMPLEMENT CK_ULONG 608 nssCKFWSession_GetDeviceError( 609 NSSCKFWSession *fwSession) 610 { 611 #ifdef NSSDEBUG 612 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 613 return (CK_ULONG)0; 614 } 615 616 if (!fwSession->mdSession) { 617 return (CK_ULONG)0; 618 } 619 #endif /* NSSDEBUG */ 620 621 if (!fwSession->mdSession->GetDeviceError) { 622 return (CK_ULONG)0; 623 } 624 625 return fwSession->mdSession->GetDeviceError(fwSession->mdSession, 626 fwSession, fwSession->mdToken, fwSession->fwToken, 627 fwSession->mdInstance, fwSession->fwInstance); 628 } 629 630 /* 631 * nssCKFWSession_Login 632 * 633 */ 634 NSS_IMPLEMENT CK_RV 635 nssCKFWSession_Login( 636 NSSCKFWSession *fwSession, 637 CK_USER_TYPE userType, 638 NSSItem *pin) 639 { 640 CK_RV error = CKR_OK; 641 CK_STATE oldState; 642 CK_STATE newState; 643 644 #ifdef NSSDEBUG 645 error = nssCKFWSession_verifyPointer(fwSession); 646 if (CKR_OK != error) { 647 return error; 648 } 649 650 switch (userType) { 651 case CKU_SO: 652 case CKU_USER: 653 break; 654 default: 655 return CKR_USER_TYPE_INVALID; 656 } 657 658 if (!pin) { 659 if (CK_TRUE != nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken)) { 660 return CKR_ARGUMENTS_BAD; 661 } 662 } 663 664 if (!fwSession->mdSession) { 665 return CKR_GENERAL_ERROR; 666 } 667 #endif /* NSSDEBUG */ 668 669 oldState = nssCKFWToken_GetSessionState(fwSession->fwToken); 670 671 /* 672 * It's not clear what happens when you're already logged in. 673 * I'll just fail; but if we decide to change, the logic is 674 * all right here. 675 */ 676 677 if (CKU_SO == userType) { 678 switch (oldState) { 679 case CKS_RO_PUBLIC_SESSION: 680 /* 681 * There's no such thing as a read-only security officer 682 * session, so fail. The error should be CKR_SESSION_READ_ONLY, 683 * except that C_Login isn't defined to return that. So we'll 684 * do CKR_SESSION_READ_ONLY_EXISTS, which is what is documented. 685 */ 686 return CKR_SESSION_READ_ONLY_EXISTS; 687 case CKS_RO_USER_FUNCTIONS: 688 return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; 689 case CKS_RW_PUBLIC_SESSION: 690 newState = 691 CKS_RW_SO_FUNCTIONS; 692 break; 693 case CKS_RW_USER_FUNCTIONS: 694 return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; 695 case CKS_RW_SO_FUNCTIONS: 696 return CKR_USER_ALREADY_LOGGED_IN; 697 default: 698 return CKR_GENERAL_ERROR; 699 } 700 } else /* CKU_USER == userType */ { 701 switch (oldState) { 702 case CKS_RO_PUBLIC_SESSION: 703 newState = 704 CKS_RO_USER_FUNCTIONS; 705 break; 706 case CKS_RO_USER_FUNCTIONS: 707 return CKR_USER_ALREADY_LOGGED_IN; 708 case CKS_RW_PUBLIC_SESSION: 709 newState = 710 CKS_RW_USER_FUNCTIONS; 711 break; 712 case CKS_RW_USER_FUNCTIONS: 713 return CKR_USER_ALREADY_LOGGED_IN; 714 case CKS_RW_SO_FUNCTIONS: 715 return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; 716 default: 717 return CKR_GENERAL_ERROR; 718 } 719 } 720 721 /* 722 * So now we're in one of three cases: 723 * 724 * Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_SO_FUNCTIONS; 725 * Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_USER_FUNCTIONS; 726 * Old == CKS_RO_PUBLIC_SESSION, New == CKS_RO_USER_FUNCTIONS; 727 */ 728 729 if (!fwSession->mdSession->Login) { 730 /* 731 * The Module doesn't want to be informed (or check the pin) 732 * it'll just rely on the Framework as needed. 733 */ 734 ; 735 } else { 736 error = fwSession->mdSession->Login(fwSession->mdSession, fwSession, 737 fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance, 738 fwSession->fwInstance, userType, pin, oldState, newState); 739 if (CKR_OK != error) { 740 return error; 741 } 742 } 743 744 (void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState); 745 return CKR_OK; 746 } 747 748 /* 749 * nssCKFWSession_Logout 750 * 751 */ 752 NSS_IMPLEMENT CK_RV 753 nssCKFWSession_Logout( 754 NSSCKFWSession *fwSession) 755 { 756 CK_RV error = CKR_OK; 757 CK_STATE oldState; 758 CK_STATE newState; 759 760 #ifdef NSSDEBUG 761 error = nssCKFWSession_verifyPointer(fwSession); 762 if (CKR_OK != error) { 763 return error; 764 } 765 766 if (!fwSession->mdSession) { 767 return CKR_GENERAL_ERROR; 768 } 769 #endif /* NSSDEBUG */ 770 771 oldState = nssCKFWToken_GetSessionState(fwSession->fwToken); 772 773 switch (oldState) { 774 case CKS_RO_PUBLIC_SESSION: 775 return CKR_USER_NOT_LOGGED_IN; 776 case CKS_RO_USER_FUNCTIONS: 777 newState = CKS_RO_PUBLIC_SESSION; 778 break; 779 case CKS_RW_PUBLIC_SESSION: 780 return CKR_USER_NOT_LOGGED_IN; 781 case CKS_RW_USER_FUNCTIONS: 782 newState = CKS_RW_PUBLIC_SESSION; 783 break; 784 case CKS_RW_SO_FUNCTIONS: 785 newState = CKS_RW_PUBLIC_SESSION; 786 break; 787 default: 788 return CKR_GENERAL_ERROR; 789 } 790 791 /* 792 * So now we're in one of three cases: 793 * 794 * Old == CKS_RW_SO_FUNCTIONS, New == CKS_RW_PUBLIC_SESSION; 795 * Old == CKS_RW_USER_FUNCTIONS, New == CKS_RW_PUBLIC_SESSION; 796 * Old == CKS_RO_USER_FUNCTIONS, New == CKS_RO_PUBLIC_SESSION; 797 */ 798 799 if (!fwSession->mdSession->Logout) { 800 /* 801 * The Module doesn't want to be informed. Okay. 802 */ 803 ; 804 } else { 805 error = fwSession->mdSession->Logout(fwSession->mdSession, fwSession, 806 fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance, 807 fwSession->fwInstance, oldState, newState); 808 if (CKR_OK != error) { 809 /* 810 * Now what?! A failure really should end up with the Framework 811 * considering it logged out, right? 812 */ 813 ; 814 } 815 } 816 817 (void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState); 818 return error; 819 } 820 821 /* 822 * nssCKFWSession_InitPIN 823 * 824 */ 825 NSS_IMPLEMENT CK_RV 826 nssCKFWSession_InitPIN( 827 NSSCKFWSession *fwSession, 828 NSSItem *pin) 829 { 830 CK_RV error = CKR_OK; 831 CK_STATE state; 832 833 #ifdef NSSDEBUG 834 error = nssCKFWSession_verifyPointer(fwSession); 835 if (CKR_OK != error) { 836 return error; 837 } 838 839 if (!fwSession->mdSession) { 840 return CKR_GENERAL_ERROR; 841 } 842 #endif /* NSSDEBUG */ 843 844 state = nssCKFWToken_GetSessionState(fwSession->fwToken); 845 if (CKS_RW_SO_FUNCTIONS != state) { 846 return CKR_USER_NOT_LOGGED_IN; 847 } 848 849 if (!pin) { 850 CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken); 851 if (CK_TRUE != has) { 852 return CKR_ARGUMENTS_BAD; 853 } 854 } 855 856 if (!fwSession->mdSession->InitPIN) { 857 return CKR_TOKEN_WRITE_PROTECTED; 858 } 859 860 error = fwSession->mdSession->InitPIN(fwSession->mdSession, fwSession, 861 fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance, 862 fwSession->fwInstance, pin); 863 864 return error; 865 } 866 867 /* 868 * nssCKFWSession_SetPIN 869 * 870 */ 871 NSS_IMPLEMENT CK_RV 872 nssCKFWSession_SetPIN( 873 NSSCKFWSession *fwSession, 874 const NSSItem *oldPin, 875 NSSItem *newPin) 876 { 877 CK_RV error = CKR_OK; 878 879 #ifdef NSSDEBUG 880 error = nssCKFWSession_verifyPointer(fwSession); 881 if (CKR_OK != error) { 882 return error; 883 } 884 885 if (!fwSession->mdSession) { 886 return CKR_GENERAL_ERROR; 887 } 888 #endif /* NSSDEBUG */ 889 890 if (!newPin) { 891 CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken); 892 if (CK_TRUE != has) { 893 return CKR_ARGUMENTS_BAD; 894 } 895 } 896 897 if (!oldPin) { 898 CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken); 899 if (CK_TRUE != has) { 900 return CKR_ARGUMENTS_BAD; 901 } 902 } 903 904 if (!fwSession->mdSession->SetPIN) { 905 return CKR_TOKEN_WRITE_PROTECTED; 906 } 907 908 error = fwSession->mdSession->SetPIN(fwSession->mdSession, fwSession, 909 fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance, 910 fwSession->fwInstance, (NSSItem *)oldPin, newPin); 911 912 return error; 913 } 914 915 /* 916 * nssCKFWSession_GetOperationStateLen 917 * 918 */ 919 NSS_IMPLEMENT CK_ULONG 920 nssCKFWSession_GetOperationStateLen( 921 NSSCKFWSession *fwSession, 922 CK_RV *pError) 923 { 924 CK_ULONG mdAmt; 925 CK_ULONG fwAmt; 926 927 #ifdef NSSDEBUG 928 if (!pError) { 929 return (CK_ULONG)0; 930 } 931 932 *pError = nssCKFWSession_verifyPointer(fwSession); 933 if (CKR_OK != *pError) { 934 return (CK_ULONG)0; 935 } 936 937 if (!fwSession->mdSession) { 938 *pError = CKR_GENERAL_ERROR; 939 return (CK_ULONG)0; 940 } 941 #endif /* NSSDEBUG */ 942 943 if (!fwSession->mdSession->GetOperationStateLen) { 944 *pError = CKR_STATE_UNSAVEABLE; 945 return (CK_ULONG)0; 946 } 947 948 /* 949 * We could check that the session is actually in some state.. 950 */ 951 952 mdAmt = fwSession->mdSession->GetOperationStateLen(fwSession->mdSession, 953 fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance, 954 fwSession->fwInstance, pError); 955 956 if (((CK_ULONG)0 == mdAmt) && (CKR_OK != *pError)) { 957 return (CK_ULONG)0; 958 } 959 960 /* 961 * Add a bit of sanity-checking 962 */ 963 fwAmt = mdAmt + 2 * sizeof(CK_ULONG); 964 965 return fwAmt; 966 } 967 968 /* 969 * nssCKFWSession_GetOperationState 970 * 971 */ 972 NSS_IMPLEMENT CK_RV 973 nssCKFWSession_GetOperationState( 974 NSSCKFWSession *fwSession, 975 NSSItem *buffer) 976 { 977 CK_RV error = CKR_OK; 978 CK_ULONG fwAmt; 979 CK_ULONG *ulBuffer; 980 NSSItem i2; 981 CK_ULONG n, i; 982 983 #ifdef NSSDEBUG 984 error = nssCKFWSession_verifyPointer(fwSession); 985 if (CKR_OK != error) { 986 return error; 987 } 988 989 if (!buffer) { 990 return CKR_ARGUMENTS_BAD; 991 } 992 993 if (!buffer->data) { 994 return CKR_ARGUMENTS_BAD; 995 } 996 997 if (!fwSession->mdSession) { 998 return CKR_GENERAL_ERROR; 999 } 1000 #endif /* NSSDEBUG */ 1001 1002 if (!fwSession->mdSession->GetOperationState) { 1003 return CKR_STATE_UNSAVEABLE; 1004 } 1005 1006 /* 1007 * Sanity-check the caller's buffer. 1008 */ 1009 1010 error = CKR_OK; 1011 fwAmt = nssCKFWSession_GetOperationStateLen(fwSession, &error); 1012 if (((CK_ULONG)0 == fwAmt) && (CKR_OK != error)) { 1013 return error; 1014 } 1015 1016 if (buffer->size < fwAmt) { 1017 return CKR_BUFFER_TOO_SMALL; 1018 } 1019 1020 ulBuffer = (CK_ULONG *)buffer->data; 1021 1022 i2.size = buffer->size - 2 * sizeof(CK_ULONG); 1023 i2.data = (void *)&ulBuffer[2]; 1024 1025 error = fwSession->mdSession->GetOperationState(fwSession->mdSession, 1026 fwSession, fwSession->mdToken, fwSession->fwToken, 1027 fwSession->mdInstance, fwSession->fwInstance, &i2); 1028 1029 if (CKR_OK != error) { 1030 return error; 1031 } 1032 1033 /* 1034 * Add a little integrety/identity check. 1035 * NOTE: right now, it's pretty stupid. 1036 * A CRC or something would be better. 1037 */ 1038 1039 ulBuffer[0] = 0x434b4657; /* CKFW */ 1040 ulBuffer[1] = 0; 1041 n = i2.size / sizeof(CK_ULONG); 1042 for (i = 0; i < n; i++) { 1043 ulBuffer[1] ^= ulBuffer[2 + i]; 1044 } 1045 1046 return CKR_OK; 1047 } 1048 1049 /* 1050 * nssCKFWSession_SetOperationState 1051 * 1052 */ 1053 NSS_IMPLEMENT CK_RV 1054 nssCKFWSession_SetOperationState( 1055 NSSCKFWSession *fwSession, 1056 NSSItem *state, 1057 NSSCKFWObject *encryptionKey, 1058 NSSCKFWObject *authenticationKey) 1059 { 1060 CK_RV error = CKR_OK; 1061 CK_ULONG *ulBuffer; 1062 CK_ULONG n, i; 1063 CK_ULONG x; 1064 NSSItem s; 1065 NSSCKMDObject *mdek; 1066 NSSCKMDObject *mdak; 1067 1068 #ifdef NSSDEBUG 1069 error = nssCKFWSession_verifyPointer(fwSession); 1070 if (CKR_OK != error) { 1071 return error; 1072 } 1073 1074 if (!state) { 1075 return CKR_ARGUMENTS_BAD; 1076 } 1077 1078 if (!state->data) { 1079 return CKR_ARGUMENTS_BAD; 1080 } 1081 1082 if (encryptionKey) { 1083 error = nssCKFWObject_verifyPointer(encryptionKey); 1084 if (CKR_OK != error) { 1085 return error; 1086 } 1087 } 1088 1089 if (authenticationKey) { 1090 error = nssCKFWObject_verifyPointer(authenticationKey); 1091 if (CKR_OK != error) { 1092 return error; 1093 } 1094 } 1095 1096 if (!fwSession->mdSession) { 1097 return CKR_GENERAL_ERROR; 1098 } 1099 #endif /* NSSDEBUG */ 1100 1101 ulBuffer = (CK_ULONG *)state->data; 1102 if (0x43b4657 != ulBuffer[0]) { 1103 return CKR_SAVED_STATE_INVALID; 1104 } 1105 n = (state->size / sizeof(CK_ULONG)) - 2; 1106 x = (CK_ULONG)0; 1107 for (i = 0; i < n; i++) { 1108 x ^= ulBuffer[2 + i]; 1109 } 1110 1111 if (x != ulBuffer[1]) { 1112 return CKR_SAVED_STATE_INVALID; 1113 } 1114 1115 if (!fwSession->mdSession->SetOperationState) { 1116 return CKR_GENERAL_ERROR; 1117 } 1118 1119 s.size = state->size - 2 * sizeof(CK_ULONG); 1120 s.data = (void *)&ulBuffer[2]; 1121 1122 if (encryptionKey) { 1123 mdek = nssCKFWObject_GetMDObject(encryptionKey); 1124 } else { 1125 mdek = (NSSCKMDObject *)NULL; 1126 } 1127 1128 if (authenticationKey) { 1129 mdak = nssCKFWObject_GetMDObject(authenticationKey); 1130 } else { 1131 mdak = (NSSCKMDObject *)NULL; 1132 } 1133 1134 error = fwSession->mdSession->SetOperationState(fwSession->mdSession, 1135 fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance, 1136 fwSession->fwInstance, &s, mdek, encryptionKey, mdak, authenticationKey); 1137 1138 if (CKR_OK != error) { 1139 return error; 1140 } 1141 1142 /* 1143 * Here'd we restore any session data 1144 */ 1145 1146 return CKR_OK; 1147 } 1148 1149 static CK_BBOOL 1150 nss_attributes_form_token_object( 1151 CK_ATTRIBUTE_PTR pTemplate, 1152 CK_ULONG ulAttributeCount) 1153 { 1154 CK_ULONG i; 1155 CK_BBOOL rv; 1156 1157 for (i = 0; i < ulAttributeCount; i++) { 1158 if (CKA_TOKEN == pTemplate[i].type) { 1159 /* If we sanity-check, we can remove this sizeof check */ 1160 if (sizeof(CK_BBOOL) == pTemplate[i].ulValueLen) { 1161 (void)nsslibc_memcpy(&rv, pTemplate[i].pValue, sizeof(CK_BBOOL)); 1162 return rv; 1163 } else { 1164 return CK_FALSE; 1165 } 1166 } 1167 } 1168 1169 return CK_FALSE; 1170 } 1171 1172 /* 1173 * nssCKFWSession_CreateObject 1174 * 1175 */ 1176 NSS_IMPLEMENT NSSCKFWObject * 1177 nssCKFWSession_CreateObject( 1178 NSSCKFWSession *fwSession, 1179 CK_ATTRIBUTE_PTR pTemplate, 1180 CK_ULONG ulAttributeCount, 1181 CK_RV *pError) 1182 { 1183 NSSArena *arena; 1184 NSSCKMDObject *mdObject; 1185 NSSCKFWObject *fwObject; 1186 CK_BBOOL isTokenObject; 1187 1188 #ifdef NSSDEBUG 1189 if (!pError) { 1190 return (NSSCKFWObject *)NULL; 1191 } 1192 1193 *pError = nssCKFWSession_verifyPointer(fwSession); 1194 if (CKR_OK != pError) { 1195 return (NSSCKFWObject *)NULL; 1196 } 1197 1198 if ((CK_ATTRIBUTE_PTR)NULL == pTemplate) { 1199 *pError = CKR_ARGUMENTS_BAD; 1200 return (NSSCKFWObject *)NULL; 1201 } 1202 1203 if (!fwSession->mdSession) { 1204 *pError = CKR_GENERAL_ERROR; 1205 return (NSSCKFWObject *)NULL; 1206 } 1207 #endif /* NSSDEBUG */ 1208 1209 /* 1210 * Here would be an excellent place to sanity-check the object. 1211 */ 1212 1213 isTokenObject = nss_attributes_form_token_object(pTemplate, ulAttributeCount); 1214 if (CK_TRUE == isTokenObject) { 1215 /* === TOKEN OBJECT === */ 1216 1217 if (!fwSession->mdSession->CreateObject) { 1218 *pError = CKR_TOKEN_WRITE_PROTECTED; 1219 return (NSSCKFWObject *)NULL; 1220 } 1221 1222 arena = nssCKFWToken_GetArena(fwSession->fwToken, pError); 1223 if (!arena) { 1224 if (CKR_OK == *pError) { 1225 *pError = CKR_GENERAL_ERROR; 1226 } 1227 return (NSSCKFWObject *)NULL; 1228 } 1229 1230 goto callmdcreateobject; 1231 } else { 1232 /* === SESSION OBJECT === */ 1233 1234 arena = nssCKFWSession_GetArena(fwSession, pError); 1235 if (!arena) { 1236 if (CKR_OK == *pError) { 1237 *pError = CKR_GENERAL_ERROR; 1238 } 1239 return (NSSCKFWObject *)NULL; 1240 } 1241 1242 if (CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects( 1243 fwSession->fwInstance)) { 1244 /* --- module handles the session object -- */ 1245 1246 if (!fwSession->mdSession->CreateObject) { 1247 *pError = CKR_GENERAL_ERROR; 1248 return (NSSCKFWObject *)NULL; 1249 } 1250 1251 goto callmdcreateobject; 1252 } else { 1253 /* --- framework handles the session object -- */ 1254 mdObject = nssCKMDSessionObject_Create(fwSession->fwToken, 1255 arena, pTemplate, ulAttributeCount, pError); 1256 goto gotmdobject; 1257 } 1258 } 1259 1260 callmdcreateobject: 1261 mdObject = fwSession->mdSession->CreateObject(fwSession->mdSession, 1262 fwSession, fwSession->mdToken, fwSession->fwToken, 1263 fwSession->mdInstance, fwSession->fwInstance, arena, pTemplate, 1264 ulAttributeCount, pError); 1265 1266 gotmdobject: 1267 if (!mdObject) { 1268 if (CKR_OK == *pError) { 1269 *pError = CKR_GENERAL_ERROR; 1270 } 1271 return (NSSCKFWObject *)NULL; 1272 } 1273 1274 fwObject = nssCKFWObject_Create(isTokenObject ? arena : NULL, mdObject, 1275 isTokenObject ? NULL 1276 : fwSession, 1277 fwSession->fwToken, fwSession->fwInstance, pError); 1278 if (!fwObject) { 1279 if (CKR_OK == *pError) { 1280 *pError = CKR_GENERAL_ERROR; 1281 } 1282 1283 if (mdObject->Destroy) { 1284 (void)mdObject->Destroy(mdObject, (NSSCKFWObject *)NULL, 1285 fwSession->mdSession, fwSession, fwSession->mdToken, 1286 fwSession->fwToken, fwSession->mdInstance, fwSession->fwInstance); 1287 } 1288 1289 return (NSSCKFWObject *)NULL; 1290 } 1291 1292 if (CK_FALSE == isTokenObject) { 1293 if (CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, fwObject)) { 1294 *pError = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject); 1295 if (CKR_OK != *pError) { 1296 nssCKFWObject_Finalize(fwObject, PR_TRUE); 1297 return (NSSCKFWObject *)NULL; 1298 } 1299 } 1300 } 1301 1302 return fwObject; 1303 } 1304 1305 /* 1306 * nssCKFWSession_CopyObject 1307 * 1308 */ 1309 NSS_IMPLEMENT NSSCKFWObject * 1310 nssCKFWSession_CopyObject( 1311 NSSCKFWSession *fwSession, 1312 NSSCKFWObject *fwObject, 1313 CK_ATTRIBUTE_PTR pTemplate, 1314 CK_ULONG ulAttributeCount, 1315 CK_RV *pError) 1316 { 1317 CK_BBOOL oldIsToken; 1318 CK_BBOOL newIsToken; 1319 CK_ULONG i; 1320 NSSCKFWObject *rv; 1321 1322 #ifdef NSSDEBUG 1323 if (!pError) { 1324 return (NSSCKFWObject *)NULL; 1325 } 1326 1327 *pError = nssCKFWSession_verifyPointer(fwSession); 1328 if (CKR_OK != *pError) { 1329 return (NSSCKFWObject *)NULL; 1330 } 1331 1332 *pError = nssCKFWObject_verifyPointer(fwObject); 1333 if (CKR_OK != *pError) { 1334 return (NSSCKFWObject *)NULL; 1335 } 1336 1337 if (!fwSession->mdSession) { 1338 *pError = CKR_GENERAL_ERROR; 1339 return (NSSCKFWObject *)NULL; 1340 } 1341 #endif /* NSSDEBUG */ 1342 1343 /* 1344 * Sanity-check object 1345 */ 1346 1347 if (!fwObject) { 1348 *pError = CKR_ARGUMENTS_BAD; 1349 return (NSSCKFWObject *)NULL; 1350 } 1351 1352 oldIsToken = nssCKFWObject_IsTokenObject(fwObject); 1353 1354 newIsToken = oldIsToken; 1355 for (i = 0; i < ulAttributeCount; i++) { 1356 if (CKA_TOKEN == pTemplate[i].type) { 1357 /* Since we sanity-checked the object, we know this is the right size. */ 1358 (void)nsslibc_memcpy(&newIsToken, pTemplate[i].pValue, sizeof(CK_BBOOL)); 1359 break; 1360 } 1361 } 1362 1363 /* 1364 * If the Module handles its session objects, or if both the new 1365 * and old object are token objects, use CopyObject if it exists. 1366 */ 1367 1368 if ((fwSession->mdSession->CopyObject) && 1369 (((CK_TRUE == oldIsToken) && (CK_TRUE == newIsToken)) || 1370 (CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects( 1371 fwSession->fwInstance)))) { 1372 /* use copy object */ 1373 NSSArena *arena; 1374 NSSCKMDObject *mdOldObject; 1375 NSSCKMDObject *mdObject; 1376 1377 mdOldObject = nssCKFWObject_GetMDObject(fwObject); 1378 1379 if (CK_TRUE == newIsToken) { 1380 arena = nssCKFWToken_GetArena(fwSession->fwToken, pError); 1381 } else { 1382 arena = nssCKFWSession_GetArena(fwSession, pError); 1383 } 1384 if (!arena) { 1385 if (CKR_OK == *pError) { 1386 *pError = CKR_GENERAL_ERROR; 1387 } 1388 return (NSSCKFWObject *)NULL; 1389 } 1390 1391 mdObject = fwSession->mdSession->CopyObject(fwSession->mdSession, 1392 fwSession, fwSession->mdToken, fwSession->fwToken, 1393 fwSession->mdInstance, fwSession->fwInstance, mdOldObject, 1394 fwObject, arena, pTemplate, ulAttributeCount, pError); 1395 if (!mdObject) { 1396 if (CKR_OK == *pError) { 1397 *pError = CKR_GENERAL_ERROR; 1398 } 1399 return (NSSCKFWObject *)NULL; 1400 } 1401 1402 rv = nssCKFWObject_Create(newIsToken ? arena : NULL, mdObject, 1403 newIsToken ? NULL 1404 : fwSession, 1405 fwSession->fwToken, fwSession->fwInstance, pError); 1406 1407 if (CK_FALSE == newIsToken) { 1408 if (CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, rv)) { 1409 *pError = nssCKFWHash_Add(fwSession->sessionObjectHash, rv, rv); 1410 if (CKR_OK != *pError) { 1411 nssCKFWObject_Finalize(rv, PR_TRUE); 1412 return (NSSCKFWObject *)NULL; 1413 } 1414 } 1415 } 1416 1417 return rv; 1418 } else { 1419 /* use create object */ 1420 NSSArena *tmpArena; 1421 CK_ATTRIBUTE_PTR newTemplate; 1422 CK_ULONG j, n, newLength, k; 1423 CK_ATTRIBUTE_TYPE_PTR oldTypes; 1424 1425 n = nssCKFWObject_GetAttributeCount(fwObject, pError); 1426 if ((0 == n) && (CKR_OK != *pError)) { 1427 return (NSSCKFWObject *)NULL; 1428 } 1429 1430 tmpArena = NSSArena_Create(); 1431 if (!tmpArena) { 1432 *pError = CKR_HOST_MEMORY; 1433 return (NSSCKFWObject *)NULL; 1434 } 1435 1436 oldTypes = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE_TYPE, n); 1437 if ((CK_ATTRIBUTE_TYPE_PTR)NULL == oldTypes) { 1438 NSSArena_Destroy(tmpArena); 1439 *pError = CKR_HOST_MEMORY; 1440 return (NSSCKFWObject *)NULL; 1441 } 1442 1443 *pError = nssCKFWObject_GetAttributeTypes(fwObject, oldTypes, n); 1444 if (CKR_OK != *pError) { 1445 NSSArena_Destroy(tmpArena); 1446 return (NSSCKFWObject *)NULL; 1447 } 1448 1449 newLength = n; 1450 for (i = 0; i < ulAttributeCount; i++) { 1451 for (j = 0; j < n; j++) { 1452 if (oldTypes[j] == pTemplate[i].type) { 1453 if ((CK_VOID_PTR)NULL == 1454 pTemplate[i].pValue) { 1455 /* Removing the attribute */ 1456 newLength--; 1457 } 1458 break; 1459 } 1460 } 1461 if (j == n) { 1462 /* Not found */ 1463 newLength++; 1464 } 1465 } 1466 1467 newTemplate = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE, newLength); 1468 if ((CK_ATTRIBUTE_PTR)NULL == newTemplate) { 1469 NSSArena_Destroy(tmpArena); 1470 *pError = CKR_HOST_MEMORY; 1471 return (NSSCKFWObject *)NULL; 1472 } 1473 1474 k = 0; 1475 for (j = 0; j < n; j++) { 1476 for (i = 0; i < ulAttributeCount; i++) { 1477 if (oldTypes[j] == pTemplate[i].type) { 1478 if ((CK_VOID_PTR)NULL == 1479 pTemplate[i].pValue) { 1480 /* This attribute is being deleted */ 1481 ; 1482 } else { 1483 /* This attribute is being replaced */ 1484 newTemplate[k].type = 1485 pTemplate[i].type; 1486 newTemplate[k].pValue = 1487 pTemplate[i].pValue; 1488 newTemplate[k].ulValueLen = 1489 pTemplate[i].ulValueLen; 1490 k++; 1491 } 1492 break; 1493 } 1494 } 1495 if (i == ulAttributeCount) { 1496 /* This attribute is being copied over from the old object */ 1497 NSSItem item, *it; 1498 item.size = 0; 1499 item.data = (void *)NULL; 1500 it = nssCKFWObject_GetAttribute(fwObject, oldTypes[j], 1501 &item, tmpArena, pError); 1502 if (!it) { 1503 if (CKR_OK == 1504 *pError) { 1505 *pError = 1506 CKR_GENERAL_ERROR; 1507 } 1508 NSSArena_Destroy(tmpArena); 1509 return (NSSCKFWObject *)NULL; 1510 } 1511 newTemplate[k].type = oldTypes[j]; 1512 newTemplate[k].pValue = it->data; 1513 newTemplate[k].ulValueLen = it->size; 1514 k++; 1515 } 1516 } 1517 /* assert that k == newLength */ 1518 1519 rv = nssCKFWSession_CreateObject(fwSession, newTemplate, newLength, pError); 1520 if (!rv) { 1521 if (CKR_OK == *pError) { 1522 *pError = CKR_GENERAL_ERROR; 1523 } 1524 NSSArena_Destroy(tmpArena); 1525 return (NSSCKFWObject *)NULL; 1526 } 1527 1528 NSSArena_Destroy(tmpArena); 1529 return rv; 1530 } 1531 } 1532 1533 /* 1534 * nssCKFWSession_FindObjectsInit 1535 * 1536 */ 1537 NSS_IMPLEMENT NSSCKFWFindObjects * 1538 nssCKFWSession_FindObjectsInit( 1539 NSSCKFWSession *fwSession, 1540 CK_ATTRIBUTE_PTR pTemplate, 1541 CK_ULONG ulAttributeCount, 1542 CK_RV *pError) 1543 { 1544 NSSCKMDFindObjects *mdfo1 = (NSSCKMDFindObjects *)NULL; 1545 NSSCKMDFindObjects *mdfo2 = (NSSCKMDFindObjects *)NULL; 1546 1547 #ifdef NSSDEBUG 1548 if (!pError) { 1549 return (NSSCKFWFindObjects *)NULL; 1550 } 1551 1552 *pError = nssCKFWSession_verifyPointer(fwSession); 1553 if (CKR_OK != *pError) { 1554 return (NSSCKFWFindObjects *)NULL; 1555 } 1556 1557 if (((CK_ATTRIBUTE_PTR)NULL == pTemplate) && (ulAttributeCount != 0)) { 1558 *pError = CKR_ARGUMENTS_BAD; 1559 return (NSSCKFWFindObjects *)NULL; 1560 } 1561 1562 if (!fwSession->mdSession) { 1563 *pError = CKR_GENERAL_ERROR; 1564 return (NSSCKFWFindObjects *)NULL; 1565 } 1566 #endif /* NSSDEBUG */ 1567 1568 if (CK_TRUE != nssCKFWInstance_GetModuleHandlesSessionObjects( 1569 fwSession->fwInstance)) { 1570 CK_ULONG i; 1571 1572 /* 1573 * Does the search criteria restrict us to token or session 1574 * objects? 1575 */ 1576 1577 for (i = 0; i < ulAttributeCount; i++) { 1578 if (CKA_TOKEN == pTemplate[i].type) { 1579 /* Yes, it does. */ 1580 CK_BBOOL isToken; 1581 if (sizeof(CK_BBOOL) != pTemplate[i].ulValueLen) { 1582 *pError = 1583 CKR_ATTRIBUTE_VALUE_INVALID; 1584 return (NSSCKFWFindObjects *)NULL; 1585 } 1586 (void)nsslibc_memcpy(&isToken, pTemplate[i].pValue, sizeof(CK_BBOOL)); 1587 1588 if (CK_TRUE == isToken) { 1589 /* Pass it on to the module's search routine */ 1590 if (!fwSession->mdSession->FindObjectsInit) { 1591 goto wrap; 1592 } 1593 1594 mdfo1 = 1595 fwSession->mdSession->FindObjectsInit(fwSession->mdSession, 1596 fwSession, fwSession->mdToken, fwSession->fwToken, 1597 fwSession->mdInstance, fwSession->fwInstance, 1598 pTemplate, ulAttributeCount, pError); 1599 } else { 1600 /* Do the search ourselves */ 1601 mdfo1 = 1602 nssCKMDFindSessionObjects_Create(fwSession->fwToken, 1603 pTemplate, ulAttributeCount, pError); 1604 } 1605 1606 if (!mdfo1) { 1607 if (CKR_OK == 1608 *pError) { 1609 *pError = 1610 CKR_GENERAL_ERROR; 1611 } 1612 return (NSSCKFWFindObjects *)NULL; 1613 } 1614 1615 goto wrap; 1616 } 1617 } 1618 1619 if (i == ulAttributeCount) { 1620 /* No, it doesn't. Do a hybrid search. */ 1621 mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession, 1622 fwSession, fwSession->mdToken, fwSession->fwToken, 1623 fwSession->mdInstance, fwSession->fwInstance, 1624 pTemplate, ulAttributeCount, pError); 1625 1626 if (!mdfo1) { 1627 if (CKR_OK == *pError) { 1628 *pError = 1629 CKR_GENERAL_ERROR; 1630 } 1631 return (NSSCKFWFindObjects *)NULL; 1632 } 1633 1634 mdfo2 = nssCKMDFindSessionObjects_Create(fwSession->fwToken, 1635 pTemplate, ulAttributeCount, pError); 1636 if (!mdfo2) { 1637 if (CKR_OK == *pError) { 1638 *pError = 1639 CKR_GENERAL_ERROR; 1640 } 1641 if (mdfo1->Final) { 1642 mdfo1->Final(mdfo1, (NSSCKFWFindObjects *)NULL, fwSession->mdSession, 1643 fwSession, fwSession->mdToken, fwSession->fwToken, 1644 fwSession->mdInstance, fwSession->fwInstance); 1645 } 1646 return (NSSCKFWFindObjects *)NULL; 1647 } 1648 1649 goto wrap; 1650 } 1651 /*NOTREACHED*/ 1652 } else { 1653 /* Module handles all its own objects. Pass on to module's search */ 1654 mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession, 1655 fwSession, fwSession->mdToken, fwSession->fwToken, 1656 fwSession->mdInstance, fwSession->fwInstance, 1657 pTemplate, ulAttributeCount, pError); 1658 1659 if (!mdfo1) { 1660 if (CKR_OK == *pError) { 1661 *pError = CKR_GENERAL_ERROR; 1662 } 1663 return (NSSCKFWFindObjects *)NULL; 1664 } 1665 1666 goto wrap; 1667 } 1668 1669 wrap: 1670 return nssCKFWFindObjects_Create(fwSession, fwSession->fwToken, 1671 fwSession->fwInstance, mdfo1, mdfo2, pError); 1672 } 1673 1674 /* 1675 * nssCKFWSession_SeedRandom 1676 * 1677 */ 1678 NSS_IMPLEMENT CK_RV 1679 nssCKFWSession_SeedRandom( 1680 NSSCKFWSession *fwSession, 1681 NSSItem *seed) 1682 { 1683 CK_RV error = CKR_OK; 1684 1685 #ifdef NSSDEBUG 1686 error = nssCKFWSession_verifyPointer(fwSession); 1687 if (CKR_OK != error) { 1688 return error; 1689 } 1690 1691 if (!seed) { 1692 return CKR_ARGUMENTS_BAD; 1693 } 1694 1695 if (!seed->data) { 1696 return CKR_ARGUMENTS_BAD; 1697 } 1698 1699 if (0 == seed->size) { 1700 return CKR_ARGUMENTS_BAD; 1701 } 1702 1703 if (!fwSession->mdSession) { 1704 return CKR_GENERAL_ERROR; 1705 } 1706 #endif /* NSSDEBUG */ 1707 1708 if (!fwSession->mdSession->SeedRandom) { 1709 return CKR_RANDOM_SEED_NOT_SUPPORTED; 1710 } 1711 1712 error = fwSession->mdSession->SeedRandom(fwSession->mdSession, fwSession, 1713 fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance, 1714 fwSession->fwInstance, seed); 1715 1716 return error; 1717 } 1718 1719 /* 1720 * nssCKFWSession_GetRandom 1721 * 1722 */ 1723 NSS_IMPLEMENT CK_RV 1724 nssCKFWSession_GetRandom( 1725 NSSCKFWSession *fwSession, 1726 NSSItem *buffer) 1727 { 1728 CK_RV error = CKR_OK; 1729 1730 #ifdef NSSDEBUG 1731 error = nssCKFWSession_verifyPointer(fwSession); 1732 if (CKR_OK != error) { 1733 return error; 1734 } 1735 1736 if (!buffer) { 1737 return CKR_ARGUMENTS_BAD; 1738 } 1739 1740 if (!buffer->data) { 1741 return CKR_ARGUMENTS_BAD; 1742 } 1743 1744 if (!fwSession->mdSession) { 1745 return CKR_GENERAL_ERROR; 1746 } 1747 #endif /* NSSDEBUG */ 1748 1749 if (!fwSession->mdSession->GetRandom) { 1750 if (CK_TRUE == nssCKFWToken_GetHasRNG(fwSession->fwToken)) { 1751 return CKR_GENERAL_ERROR; 1752 } else { 1753 return CKR_RANDOM_NO_RNG; 1754 } 1755 } 1756 1757 if (0 == buffer->size) { 1758 return CKR_OK; 1759 } 1760 1761 error = fwSession->mdSession->GetRandom(fwSession->mdSession, fwSession, 1762 fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance, 1763 fwSession->fwInstance, buffer); 1764 1765 return error; 1766 } 1767 1768 /* 1769 * nssCKFWSession_SetCurrentCryptoOperation 1770 */ 1771 NSS_IMPLEMENT void 1772 nssCKFWSession_SetCurrentCryptoOperation( 1773 NSSCKFWSession *fwSession, 1774 NSSCKFWCryptoOperation *fwOperation, 1775 NSSCKFWCryptoOperationState state) 1776 { 1777 #ifdef NSSDEBUG 1778 CK_RV error = CKR_OK; 1779 error = nssCKFWSession_verifyPointer(fwSession); 1780 if (CKR_OK != error) { 1781 return; 1782 } 1783 1784 if (state >= NSSCKFWCryptoOperationState_Max) { 1785 return; 1786 } 1787 1788 if (!fwSession->mdSession) { 1789 return; 1790 } 1791 #endif /* NSSDEBUG */ 1792 fwSession->fwOperationArray[state] = fwOperation; 1793 return; 1794 } 1795 1796 /* 1797 * nssCKFWSession_GetCurrentCryptoOperation 1798 */ 1799 NSS_IMPLEMENT NSSCKFWCryptoOperation * 1800 nssCKFWSession_GetCurrentCryptoOperation( 1801 NSSCKFWSession *fwSession, 1802 NSSCKFWCryptoOperationState state) 1803 { 1804 #ifdef NSSDEBUG 1805 CK_RV error = CKR_OK; 1806 error = nssCKFWSession_verifyPointer(fwSession); 1807 if (CKR_OK != error) { 1808 return (NSSCKFWCryptoOperation *)NULL; 1809 } 1810 1811 if (state >= NSSCKFWCryptoOperationState_Max) { 1812 return (NSSCKFWCryptoOperation *)NULL; 1813 } 1814 1815 if (!fwSession->mdSession) { 1816 return (NSSCKFWCryptoOperation *)NULL; 1817 } 1818 #endif /* NSSDEBUG */ 1819 return fwSession->fwOperationArray[state]; 1820 } 1821 1822 /* 1823 * nssCKFWSession_Final 1824 */ 1825 NSS_IMPLEMENT CK_RV 1826 nssCKFWSession_Final( 1827 NSSCKFWSession *fwSession, 1828 NSSCKFWCryptoOperationType type, 1829 NSSCKFWCryptoOperationState state, 1830 CK_BYTE_PTR outBuf, 1831 CK_ULONG_PTR outBufLen) 1832 { 1833 NSSCKFWCryptoOperation *fwOperation; 1834 NSSItem outputBuffer; 1835 CK_RV error = CKR_OK; 1836 1837 #ifdef NSSDEBUG 1838 error = nssCKFWSession_verifyPointer(fwSession); 1839 if (CKR_OK != error) { 1840 return error; 1841 } 1842 1843 if (!fwSession->mdSession) { 1844 return CKR_GENERAL_ERROR; 1845 } 1846 #endif /* NSSDEBUG */ 1847 1848 /* make sure we have a valid operation initialized */ 1849 fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state); 1850 if (!fwOperation) { 1851 return CKR_OPERATION_NOT_INITIALIZED; 1852 } 1853 1854 /* make sure it's the correct type */ 1855 if (type != nssCKFWCryptoOperation_GetType(fwOperation)) { 1856 return CKR_OPERATION_NOT_INITIALIZED; 1857 } 1858 1859 /* handle buffer issues, note for Verify, the type is an input buffer. */ 1860 if (NSSCKFWCryptoOperationType_Verify == type) { 1861 if ((CK_BYTE_PTR)NULL == outBuf) { 1862 error = CKR_ARGUMENTS_BAD; 1863 goto done; 1864 } 1865 } else { 1866 CK_ULONG len = nssCKFWCryptoOperation_GetFinalLength(fwOperation, &error); 1867 CK_ULONG maxBufLen = *outBufLen; 1868 1869 if (CKR_OK != error) { 1870 goto done; 1871 } 1872 *outBufLen = len; 1873 if ((CK_BYTE_PTR)NULL == outBuf) { 1874 return CKR_OK; 1875 } 1876 1877 if (len > maxBufLen) { 1878 return CKR_BUFFER_TOO_SMALL; 1879 } 1880 } 1881 outputBuffer.data = outBuf; 1882 outputBuffer.size = *outBufLen; 1883 1884 error = nssCKFWCryptoOperation_Final(fwOperation, &outputBuffer); 1885 done: 1886 if (CKR_BUFFER_TOO_SMALL == error) { 1887 return error; 1888 } 1889 /* clean up our state */ 1890 nssCKFWCryptoOperation_Destroy(fwOperation); 1891 nssCKFWSession_SetCurrentCryptoOperation(fwSession, NULL, state); 1892 return error; 1893 } 1894 1895 /* 1896 * nssCKFWSession_Update 1897 */ 1898 NSS_IMPLEMENT CK_RV 1899 nssCKFWSession_Update( 1900 NSSCKFWSession *fwSession, 1901 NSSCKFWCryptoOperationType type, 1902 NSSCKFWCryptoOperationState state, 1903 CK_BYTE_PTR inBuf, 1904 CK_ULONG inBufLen, 1905 CK_BYTE_PTR outBuf, 1906 CK_ULONG_PTR outBufLen) 1907 { 1908 NSSCKFWCryptoOperation *fwOperation; 1909 NSSItem inputBuffer; 1910 NSSItem outputBuffer; 1911 CK_ULONG len; 1912 CK_ULONG maxBufLen; 1913 CK_RV error = CKR_OK; 1914 1915 #ifdef NSSDEBUG 1916 error = nssCKFWSession_verifyPointer(fwSession); 1917 if (CKR_OK != error) { 1918 return error; 1919 } 1920 1921 if (!fwSession->mdSession) { 1922 return CKR_GENERAL_ERROR; 1923 } 1924 #endif /* NSSDEBUG */ 1925 1926 /* make sure we have a valid operation initialized */ 1927 fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state); 1928 if (!fwOperation) { 1929 return CKR_OPERATION_NOT_INITIALIZED; 1930 } 1931 1932 /* make sure it's the correct type */ 1933 if (type != nssCKFWCryptoOperation_GetType(fwOperation)) { 1934 return CKR_OPERATION_NOT_INITIALIZED; 1935 } 1936 1937 inputBuffer.data = inBuf; 1938 inputBuffer.size = inBufLen; 1939 1940 /* handle buffer issues, note for Verify, the type is an input buffer. */ 1941 len = nssCKFWCryptoOperation_GetOperationLength(fwOperation, &inputBuffer, 1942 &error); 1943 if (CKR_OK != error) { 1944 return error; 1945 } 1946 maxBufLen = *outBufLen; 1947 1948 *outBufLen = len; 1949 if ((CK_BYTE_PTR)NULL == outBuf) { 1950 return CKR_OK; 1951 } 1952 1953 if (len > maxBufLen) { 1954 return CKR_BUFFER_TOO_SMALL; 1955 } 1956 outputBuffer.data = outBuf; 1957 outputBuffer.size = *outBufLen; 1958 1959 return nssCKFWCryptoOperation_Update(fwOperation, 1960 &inputBuffer, &outputBuffer); 1961 } 1962 1963 /* 1964 * nssCKFWSession_DigestUpdate 1965 */ 1966 NSS_IMPLEMENT CK_RV 1967 nssCKFWSession_DigestUpdate( 1968 NSSCKFWSession *fwSession, 1969 NSSCKFWCryptoOperationType type, 1970 NSSCKFWCryptoOperationState state, 1971 CK_BYTE_PTR inBuf, 1972 CK_ULONG inBufLen) 1973 { 1974 NSSCKFWCryptoOperation *fwOperation; 1975 NSSItem inputBuffer; 1976 CK_RV error = CKR_OK; 1977 1978 #ifdef NSSDEBUG 1979 error = nssCKFWSession_verifyPointer(fwSession); 1980 if (CKR_OK != error) { 1981 return error; 1982 } 1983 1984 if (!fwSession->mdSession) { 1985 return CKR_GENERAL_ERROR; 1986 } 1987 #endif /* NSSDEBUG */ 1988 1989 /* make sure we have a valid operation initialized */ 1990 fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state); 1991 if (!fwOperation) { 1992 return CKR_OPERATION_NOT_INITIALIZED; 1993 } 1994 1995 /* make sure it's the correct type */ 1996 if (type != nssCKFWCryptoOperation_GetType(fwOperation)) { 1997 return CKR_OPERATION_NOT_INITIALIZED; 1998 } 1999 2000 inputBuffer.data = inBuf; 2001 inputBuffer.size = inBufLen; 2002 2003 error = nssCKFWCryptoOperation_DigestUpdate(fwOperation, &inputBuffer); 2004 return error; 2005 } 2006 2007 /* 2008 * nssCKFWSession_DigestUpdate 2009 */ 2010 NSS_IMPLEMENT CK_RV 2011 nssCKFWSession_DigestKey( 2012 NSSCKFWSession *fwSession, 2013 NSSCKFWObject *fwKey) 2014 { 2015 NSSCKFWCryptoOperation *fwOperation; 2016 NSSItem *inputBuffer; 2017 CK_RV error = CKR_OK; 2018 2019 #ifdef NSSDEBUG 2020 error = nssCKFWSession_verifyPointer(fwSession); 2021 if (CKR_OK != error) { 2022 return error; 2023 } 2024 2025 if (!fwSession->mdSession) { 2026 return CKR_GENERAL_ERROR; 2027 } 2028 #endif /* NSSDEBUG */ 2029 2030 /* make sure we have a valid operation initialized */ 2031 fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, 2032 NSSCKFWCryptoOperationState_Digest); 2033 if (!fwOperation) { 2034 return CKR_OPERATION_NOT_INITIALIZED; 2035 } 2036 2037 /* make sure it's the correct type */ 2038 if (NSSCKFWCryptoOperationType_Digest != 2039 nssCKFWCryptoOperation_GetType(fwOperation)) { 2040 return CKR_OPERATION_NOT_INITIALIZED; 2041 } 2042 2043 error = nssCKFWCryptoOperation_DigestKey(fwOperation, fwKey); 2044 if (CKR_FUNCTION_FAILED != error) { 2045 return error; 2046 } 2047 2048 /* no machine depended way for this to happen, do it by hand */ 2049 inputBuffer = nssCKFWObject_GetAttribute(fwKey, CKA_VALUE, NULL, NULL, &error); 2050 if (!inputBuffer) { 2051 /* couldn't get the value, just fail then */ 2052 return error; 2053 } 2054 error = nssCKFWCryptoOperation_DigestUpdate(fwOperation, inputBuffer); 2055 nssItem_Destroy(inputBuffer); 2056 return error; 2057 } 2058 2059 /* 2060 * nssCKFWSession_UpdateFinal 2061 */ 2062 NSS_IMPLEMENT CK_RV 2063 nssCKFWSession_UpdateFinal( 2064 NSSCKFWSession *fwSession, 2065 NSSCKFWCryptoOperationType type, 2066 NSSCKFWCryptoOperationState state, 2067 CK_BYTE_PTR inBuf, 2068 CK_ULONG inBufLen, 2069 CK_BYTE_PTR outBuf, 2070 CK_ULONG_PTR outBufLen) 2071 { 2072 NSSCKFWCryptoOperation *fwOperation; 2073 NSSItem inputBuffer; 2074 NSSItem outputBuffer; 2075 PRBool isEncryptDecrypt; 2076 CK_RV error = CKR_OK; 2077 2078 #ifdef NSSDEBUG 2079 error = nssCKFWSession_verifyPointer(fwSession); 2080 if (CKR_OK != error) { 2081 return error; 2082 } 2083 2084 if (!fwSession->mdSession) { 2085 return CKR_GENERAL_ERROR; 2086 } 2087 #endif /* NSSDEBUG */ 2088 2089 /* make sure we have a valid operation initialized */ 2090 fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state); 2091 if (!fwOperation) { 2092 return CKR_OPERATION_NOT_INITIALIZED; 2093 } 2094 2095 /* make sure it's the correct type */ 2096 if (type != nssCKFWCryptoOperation_GetType(fwOperation)) { 2097 return CKR_OPERATION_NOT_INITIALIZED; 2098 } 2099 2100 inputBuffer.data = inBuf; 2101 inputBuffer.size = inBufLen; 2102 isEncryptDecrypt = (PRBool)((NSSCKFWCryptoOperationType_Encrypt == type) || 2103 (NSSCKFWCryptoOperationType_Decrypt == type)); 2104 2105 /* handle buffer issues, note for Verify, the type is an input buffer. */ 2106 if (NSSCKFWCryptoOperationType_Verify == type) { 2107 if ((CK_BYTE_PTR)NULL == outBuf) { 2108 error = CKR_ARGUMENTS_BAD; 2109 goto done; 2110 } 2111 } else { 2112 CK_ULONG maxBufLen = *outBufLen; 2113 CK_ULONG len; 2114 2115 len = (isEncryptDecrypt) ? nssCKFWCryptoOperation_GetOperationLength(fwOperation, 2116 &inputBuffer, &error) 2117 : nssCKFWCryptoOperation_GetFinalLength(fwOperation, &error); 2118 2119 if (CKR_OK != error) { 2120 goto done; 2121 } 2122 2123 *outBufLen = len; 2124 if ((CK_BYTE_PTR)NULL == outBuf) { 2125 return CKR_OK; 2126 } 2127 2128 if (len > maxBufLen) { 2129 return CKR_BUFFER_TOO_SMALL; 2130 } 2131 } 2132 outputBuffer.data = outBuf; 2133 outputBuffer.size = *outBufLen; 2134 2135 error = nssCKFWCryptoOperation_UpdateFinal(fwOperation, 2136 &inputBuffer, &outputBuffer); 2137 2138 /* UpdateFinal isn't support, manually use Update and Final */ 2139 if (CKR_FUNCTION_FAILED == error) { 2140 error = isEncryptDecrypt ? nssCKFWCryptoOperation_Update(fwOperation, &inputBuffer, &outputBuffer) 2141 : nssCKFWCryptoOperation_DigestUpdate(fwOperation, &inputBuffer); 2142 2143 if (CKR_OK == error) { 2144 error = nssCKFWCryptoOperation_Final(fwOperation, &outputBuffer); 2145 } 2146 } 2147 2148 done: 2149 if (CKR_BUFFER_TOO_SMALL == error) { 2150 /* if we return CKR_BUFFER_TOO_SMALL, we the caller is not expecting. 2151 * the crypto state to be freed */ 2152 return error; 2153 } 2154 2155 /* clean up our state */ 2156 nssCKFWCryptoOperation_Destroy(fwOperation); 2157 nssCKFWSession_SetCurrentCryptoOperation(fwSession, NULL, state); 2158 return error; 2159 } 2160 2161 NSS_IMPLEMENT CK_RV 2162 nssCKFWSession_UpdateCombo( 2163 NSSCKFWSession *fwSession, 2164 NSSCKFWCryptoOperationType encryptType, 2165 NSSCKFWCryptoOperationType digestType, 2166 NSSCKFWCryptoOperationState digestState, 2167 CK_BYTE_PTR inBuf, 2168 CK_ULONG inBufLen, 2169 CK_BYTE_PTR outBuf, 2170 CK_ULONG_PTR outBufLen) 2171 { 2172 NSSCKFWCryptoOperation *fwOperation; 2173 NSSCKFWCryptoOperation *fwPeerOperation; 2174 NSSItem inputBuffer; 2175 NSSItem outputBuffer; 2176 CK_ULONG maxBufLen = *outBufLen; 2177 CK_ULONG len; 2178 CK_RV error = CKR_OK; 2179 2180 #ifdef NSSDEBUG 2181 error = nssCKFWSession_verifyPointer(fwSession); 2182 if (CKR_OK != error) { 2183 return error; 2184 } 2185 2186 if (!fwSession->mdSession) { 2187 return CKR_GENERAL_ERROR; 2188 } 2189 #endif /* NSSDEBUG */ 2190 2191 /* make sure we have a valid operation initialized */ 2192 fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, 2193 NSSCKFWCryptoOperationState_EncryptDecrypt); 2194 if (!fwOperation) { 2195 return CKR_OPERATION_NOT_INITIALIZED; 2196 } 2197 2198 /* make sure it's the correct type */ 2199 if (encryptType != nssCKFWCryptoOperation_GetType(fwOperation)) { 2200 return CKR_OPERATION_NOT_INITIALIZED; 2201 } 2202 /* make sure we have a valid operation initialized */ 2203 fwPeerOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, 2204 digestState); 2205 if (!fwPeerOperation) { 2206 return CKR_OPERATION_NOT_INITIALIZED; 2207 } 2208 2209 /* make sure it's the correct type */ 2210 if (digestType != nssCKFWCryptoOperation_GetType(fwOperation)) { 2211 return CKR_OPERATION_NOT_INITIALIZED; 2212 } 2213 2214 inputBuffer.data = inBuf; 2215 inputBuffer.size = inBufLen; 2216 len = nssCKFWCryptoOperation_GetOperationLength(fwOperation, 2217 &inputBuffer, &error); 2218 if (CKR_OK != error) { 2219 return error; 2220 } 2221 2222 *outBufLen = len; 2223 if ((CK_BYTE_PTR)NULL == outBuf) { 2224 return CKR_OK; 2225 } 2226 2227 if (len > maxBufLen) { 2228 return CKR_BUFFER_TOO_SMALL; 2229 } 2230 2231 outputBuffer.data = outBuf; 2232 outputBuffer.size = *outBufLen; 2233 2234 error = nssCKFWCryptoOperation_UpdateCombo(fwOperation, fwPeerOperation, 2235 &inputBuffer, &outputBuffer); 2236 if (CKR_FUNCTION_FAILED == error) { 2237 PRBool isEncrypt = 2238 (PRBool)(NSSCKFWCryptoOperationType_Encrypt == encryptType); 2239 2240 if (isEncrypt) { 2241 error = nssCKFWCryptoOperation_DigestUpdate(fwPeerOperation, 2242 &inputBuffer); 2243 if (CKR_OK != error) { 2244 return error; 2245 } 2246 } 2247 error = nssCKFWCryptoOperation_Update(fwOperation, 2248 &inputBuffer, &outputBuffer); 2249 if (CKR_OK != error) { 2250 return error; 2251 } 2252 if (!isEncrypt) { 2253 error = nssCKFWCryptoOperation_DigestUpdate(fwPeerOperation, 2254 &outputBuffer); 2255 } 2256 } 2257 return error; 2258 } 2259 2260 /* 2261 * NSSCKFWSession_GetMDSession 2262 * 2263 */ 2264 2265 NSS_IMPLEMENT NSSCKMDSession * 2266 NSSCKFWSession_GetMDSession( 2267 NSSCKFWSession *fwSession) 2268 { 2269 #ifdef DEBUG 2270 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 2271 return (NSSCKMDSession *)NULL; 2272 } 2273 #endif /* DEBUG */ 2274 2275 return nssCKFWSession_GetMDSession(fwSession); 2276 } 2277 2278 /* 2279 * NSSCKFWSession_GetArena 2280 * 2281 */ 2282 2283 NSS_IMPLEMENT NSSArena * 2284 NSSCKFWSession_GetArena( 2285 NSSCKFWSession *fwSession, 2286 CK_RV *pError) 2287 { 2288 #ifdef DEBUG 2289 if (!pError) { 2290 return (NSSArena *)NULL; 2291 } 2292 2293 *pError = nssCKFWSession_verifyPointer(fwSession); 2294 if (CKR_OK != *pError) { 2295 return (NSSArena *)NULL; 2296 } 2297 #endif /* DEBUG */ 2298 2299 return nssCKFWSession_GetArena(fwSession, pError); 2300 } 2301 2302 /* 2303 * NSSCKFWSession_CallNotification 2304 * 2305 */ 2306 2307 NSS_IMPLEMENT CK_RV 2308 NSSCKFWSession_CallNotification( 2309 NSSCKFWSession *fwSession, 2310 CK_NOTIFICATION event) 2311 { 2312 #ifdef DEBUG 2313 CK_RV error = CKR_OK; 2314 2315 error = nssCKFWSession_verifyPointer(fwSession); 2316 if (CKR_OK != error) { 2317 return error; 2318 } 2319 #endif /* DEBUG */ 2320 2321 return nssCKFWSession_CallNotification(fwSession, event); 2322 } 2323 2324 /* 2325 * NSSCKFWSession_IsRWSession 2326 * 2327 */ 2328 2329 NSS_IMPLEMENT CK_BBOOL 2330 NSSCKFWSession_IsRWSession( 2331 NSSCKFWSession *fwSession) 2332 { 2333 #ifdef DEBUG 2334 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 2335 return CK_FALSE; 2336 } 2337 #endif /* DEBUG */ 2338 2339 return nssCKFWSession_IsRWSession(fwSession); 2340 } 2341 2342 /* 2343 * NSSCKFWSession_IsSO 2344 * 2345 */ 2346 2347 NSS_IMPLEMENT CK_BBOOL 2348 NSSCKFWSession_IsSO( 2349 NSSCKFWSession *fwSession) 2350 { 2351 #ifdef DEBUG 2352 if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) { 2353 return CK_FALSE; 2354 } 2355 #endif /* DEBUG */ 2356 2357 return nssCKFWSession_IsSO(fwSession); 2358 } 2359 2360 NSS_IMPLEMENT NSSCKFWCryptoOperation * 2361 NSSCKFWSession_GetCurrentCryptoOperation( 2362 NSSCKFWSession *fwSession, 2363 NSSCKFWCryptoOperationState state) 2364 { 2365 #ifdef DEBUG 2366 CK_RV error = CKR_OK; 2367 error = nssCKFWSession_verifyPointer(fwSession); 2368 if (CKR_OK != error) { 2369 return (NSSCKFWCryptoOperation *)NULL; 2370 } 2371 2372 if (state >= NSSCKFWCryptoOperationState_Max) { 2373 return (NSSCKFWCryptoOperation *)NULL; 2374 } 2375 #endif /* DEBUG */ 2376 return nssCKFWSession_GetCurrentCryptoOperation(fwSession, state); 2377 } 2378 2379 /* 2380 * NSSCKFWSession_GetFWSlot 2381 * 2382 */ 2383 2384 NSS_IMPLEMENT NSSCKFWSlot * 2385 NSSCKFWSession_GetFWSlot( 2386 NSSCKFWSession *fwSession) 2387 { 2388 return nssCKFWSession_GetFWSlot(fwSession); 2389 }