Back to index

lightning-sunbird  0.9+nobinonly
session.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #ifdef DEBUG
00038 static const char CVS_ID[] = "@(#) $RCSfile: session.c,v $ $Revision: 1.8.28.1 $ $Date: 2006/04/19 23:49:53 $";
00039 #endif /* DEBUG */
00040 
00041 /*
00042  * session.c
00043  *
00044  * This file implements the NSSCKFWSession type and methods.
00045  */
00046 
00047 #ifndef CK_T
00048 #include "ck.h"
00049 #endif /* CK_T */
00050 
00051 /*
00052  * NSSCKFWSession
00053  *
00054  *  -- create/destroy --
00055  *  nssCKFWSession_Create
00056  *  nssCKFWSession_Destroy
00057  *
00058  *  -- public accessors --
00059  *  NSSCKFWSession_GetMDSession
00060  *  NSSCKFWSession_GetArena
00061  *  NSSCKFWSession_CallNotification
00062  *  NSSCKFWSession_IsRWSession
00063  *  NSSCKFWSession_IsSO
00064  *
00065  *  -- implement public accessors --
00066  *  nssCKFWSession_GetMDSession
00067  *  nssCKFWSession_GetArena
00068  *  nssCKFWSession_CallNotification
00069  *  nssCKFWSession_IsRWSession
00070  *  nssCKFWSession_IsSO
00071  *
00072  *  -- private accessors --
00073  *  nssCKFWSession_GetSlot
00074  *  nssCKFWSession_GetSessionState
00075  *  nssCKFWSession_SetFWFindObjects
00076  *  nssCKFWSession_GetFWFindObjects
00077  *  nssCKFWSession_SetMDSession
00078  *  nssCKFWSession_SetHandle
00079  *  nssCKFWSession_GetHandle
00080  *  nssCKFWSession_RegisterSessionObject
00081  *  nssCKFWSession_DeegisterSessionObject
00082  *
00083  *  -- module fronts --
00084  *  nssCKFWSession_GetDeviceError
00085  *  nssCKFWSession_Login
00086  *  nssCKFWSession_Logout
00087  *  nssCKFWSession_InitPIN
00088  *  nssCKFWSession_SetPIN
00089  *  nssCKFWSession_GetOperationStateLen
00090  *  nssCKFWSession_GetOperationState
00091  *  nssCKFWSession_SetOperationState
00092  *  nssCKFWSession_CreateObject
00093  *  nssCKFWSession_CopyObject
00094  *  nssCKFWSession_FindObjectsInit
00095  *  nssCKFWSession_SeedRandom
00096  *  nssCKFWSession_GetRandom
00097  */
00098 
00099 struct NSSCKFWSessionStr {
00100   NSSArena *arena;
00101   NSSCKMDSession *mdSession;
00102   NSSCKFWToken *fwToken;
00103   NSSCKMDToken *mdToken;
00104   NSSCKFWInstance *fwInstance;
00105   NSSCKMDInstance *mdInstance;
00106   CK_VOID_PTR pApplication;
00107   CK_NOTIFY Notify;
00108 
00109   /*
00110    * Everything above is set at creation time, and then not modified.
00111    * The items below are atomic.  No locking required.  If we fear
00112    * about pointer-copies being nonatomic, we'll lock fwFindObjects.
00113    */
00114 
00115   CK_BBOOL rw;
00116   NSSCKFWFindObjects *fwFindObjects;
00117   nssCKFWHash *sessionObjectHash;
00118   CK_SESSION_HANDLE hSession;
00119 };
00120 
00121 #ifdef DEBUG
00122 /*
00123  * But first, the pointer-tracking stuff.
00124  *
00125  * NOTE: the pointer-tracking support in NSS/base currently relies
00126  * upon NSPR's CallOnce support.  That, however, relies upon NSPR's
00127  * locking, which is tied into the runtime.  We need a pointer-tracker
00128  * implementation that uses the locks supplied through C_Initialize.
00129  * That support, however, can be filled in later.  So for now, I'll
00130  * just do this routines as no-ops.
00131  */
00132 
00133 static CK_RV
00134 session_add_pointer
00135 (
00136   const NSSCKFWSession *fwSession
00137 )
00138 {
00139   return CKR_OK;
00140 }
00141 
00142 static CK_RV
00143 session_remove_pointer
00144 (
00145   const NSSCKFWSession *fwSession
00146 )
00147 {
00148   return CKR_OK;
00149 }
00150 
00151 NSS_IMPLEMENT CK_RV
00152 nssCKFWSession_verifyPointer
00153 (
00154   const NSSCKFWSession *fwSession
00155 )
00156 {
00157   return CKR_OK;
00158 }
00159 
00160 #endif /* DEBUG */
00161 
00162 /*
00163  * nssCKFWSession_Create
00164  *
00165  */
00166 NSS_IMPLEMENT NSSCKFWSession *
00167 nssCKFWSession_Create
00168 (
00169   NSSCKFWToken *fwToken,
00170   CK_BBOOL rw,
00171   CK_VOID_PTR pApplication,
00172   CK_NOTIFY Notify,
00173   CK_RV *pError
00174 )
00175 {
00176   NSSArena *arena = (NSSArena *)NULL;
00177   NSSCKFWSession *fwSession;
00178   NSSCKFWSlot *fwSlot;
00179 
00180 #ifdef NSSDEBUG
00181   if( (CK_RV *)NULL == pError ) {
00182     return (NSSCKFWSession *)NULL;
00183   }
00184 
00185   *pError = nssCKFWToken_verifyPointer(fwToken);
00186   if( CKR_OK != *pError ) {
00187     return (NSSCKFWSession *)NULL;
00188   }
00189 #endif /* NSSDEBUG */
00190 
00191   arena = NSSArena_Create();
00192   if( (NSSArena *)NULL == arena ) {
00193     *pError = CKR_HOST_MEMORY;
00194     return (NSSCKFWSession *)NULL;
00195   }
00196 
00197   fwSession = nss_ZNEW(arena, NSSCKFWSession);
00198   if( (NSSCKFWSession *)NULL == fwSession ) {
00199     *pError = CKR_HOST_MEMORY;
00200     goto loser;
00201   }
00202 
00203   fwSession->arena = arena;
00204   fwSession->mdSession = (NSSCKMDSession *)NULL; /* set later */
00205   fwSession->fwToken = fwToken;
00206   fwSession->mdToken = nssCKFWToken_GetMDToken(fwToken);
00207 
00208   fwSlot = nssCKFWToken_GetFWSlot(fwToken);
00209   fwSession->fwInstance = nssCKFWSlot_GetFWInstance(fwSlot);
00210   fwSession->mdInstance = nssCKFWSlot_GetMDInstance(fwSlot);
00211 
00212   fwSession->rw = rw;
00213   fwSession->pApplication = pApplication;
00214   fwSession->Notify = Notify;
00215 
00216   fwSession->fwFindObjects = (NSSCKFWFindObjects *)NULL;
00217 
00218   fwSession->sessionObjectHash = nssCKFWHash_Create(fwSession->fwInstance, arena, pError);
00219   if( (nssCKFWHash *)NULL == fwSession->sessionObjectHash ) {
00220     if( CKR_OK == *pError ) {
00221       *pError = CKR_GENERAL_ERROR;
00222     }
00223     goto loser;
00224   }
00225 
00226 #ifdef DEBUG
00227   *pError = session_add_pointer(fwSession);
00228   if( CKR_OK != *pError ) {
00229     goto loser;
00230   }
00231 #endif /* DEBUG */
00232 
00233   return fwSession;
00234 
00235  loser:
00236   if( (NSSArena *)NULL != arena ) {
00237     if( fwSession && (nssCKFWHash *)NULL != fwSession->sessionObjectHash ) {
00238       (void)nssCKFWHash_Destroy(fwSession->sessionObjectHash);
00239     }
00240     NSSArena_Destroy(arena);
00241   }
00242 
00243   return (NSSCKFWSession *)NULL;
00244 }
00245 
00246 static void
00247 nss_ckfw_session_object_destroy_iterator
00248 (
00249   const void *key,
00250   void *value,
00251   void *closure
00252 )
00253 {
00254   NSSCKFWObject *fwObject = (NSSCKFWObject *)value;
00255   nssCKFWObject_Finalize(fwObject);
00256 }
00257 
00258 /*
00259  * nssCKFWSession_Destroy
00260  *
00261  */
00262 NSS_IMPLEMENT CK_RV
00263 nssCKFWSession_Destroy
00264 (
00265   NSSCKFWSession *fwSession,
00266   CK_BBOOL removeFromTokenHash
00267 )
00268 {
00269   CK_RV error = CKR_OK;
00270   nssCKFWHash *sessionObjectHash;
00271 
00272 #ifdef NSSDEBUG
00273   error = nssCKFWSession_verifyPointer(fwSession);
00274   if( CKR_OK != error ) {
00275     return error;
00276   }
00277 #endif /* NSSDEBUG */
00278 
00279   if( removeFromTokenHash ) {
00280     error = nssCKFWToken_RemoveSession(fwSession->fwToken, fwSession);
00281   }
00282 
00283   /*
00284    * Invalidate session objects
00285    */
00286 
00287   sessionObjectHash = fwSession->sessionObjectHash;
00288   fwSession->sessionObjectHash = (nssCKFWHash *)NULL;
00289 
00290   nssCKFWHash_Iterate(sessionObjectHash, 
00291                       nss_ckfw_session_object_destroy_iterator, 
00292                       (void *)NULL);
00293 
00294 #ifdef DEBUG
00295   (void)session_remove_pointer(fwSession);
00296 #endif /* DEBUG */
00297   (void)nssCKFWHash_Destroy(sessionObjectHash);
00298   NSSArena_Destroy(fwSession->arena);
00299 
00300   return error;
00301 }
00302 
00303 /*
00304  * nssCKFWSession_GetMDSession
00305  *
00306  */
00307 NSS_IMPLEMENT NSSCKMDSession *
00308 nssCKFWSession_GetMDSession
00309 (
00310   NSSCKFWSession *fwSession
00311 )
00312 {
00313 #ifdef NSSDEBUG
00314   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
00315     return (NSSCKMDSession *)NULL;
00316   }
00317 #endif /* NSSDEBUG */
00318 
00319   return fwSession->mdSession;
00320 }
00321 
00322 /*
00323  * nssCKFWSession_GetArena
00324  *
00325  */
00326 NSS_IMPLEMENT NSSArena *
00327 nssCKFWSession_GetArena
00328 (
00329   NSSCKFWSession *fwSession,
00330   CK_RV *pError
00331 )
00332 {
00333 #ifdef NSSDEBUG
00334   if( (CK_RV *)NULL == pError ) {
00335     return (NSSArena *)NULL;
00336   }
00337 
00338   *pError = nssCKFWSession_verifyPointer(fwSession);
00339   if( CKR_OK != *pError ) {
00340     return (NSSArena *)NULL;
00341   }
00342 #endif /* NSSDEBUG */
00343 
00344   return fwSession->arena;
00345 }
00346 
00347 /*
00348  * nssCKFWSession_CallNotification
00349  *
00350  */
00351 NSS_IMPLEMENT CK_RV
00352 nssCKFWSession_CallNotification
00353 (
00354   NSSCKFWSession *fwSession,
00355   CK_NOTIFICATION event
00356 )
00357 {
00358   CK_RV error = CKR_OK;
00359   CK_SESSION_HANDLE handle;
00360 
00361 #ifdef NSSDEBUG
00362   error = nssCKFWSession_verifyPointer(fwSession);
00363   if( CKR_OK != error ) {
00364     return error;
00365   }
00366 #endif /* NSSDEBUG */
00367 
00368   if( (CK_NOTIFY)NULL == fwSession->Notify ) {
00369     return CKR_OK;
00370   }
00371 
00372   handle = nssCKFWInstance_FindSessionHandle(fwSession->fwInstance, fwSession);
00373   if( (CK_SESSION_HANDLE)0 == handle ) {
00374     return CKR_GENERAL_ERROR;
00375   }
00376 
00377   error = fwSession->Notify(handle, event, fwSession->pApplication);
00378 
00379   return error;
00380 }
00381 
00382 /*
00383  * nssCKFWSession_IsRWSession
00384  *
00385  */
00386 NSS_IMPLEMENT CK_BBOOL
00387 nssCKFWSession_IsRWSession
00388 (
00389   NSSCKFWSession *fwSession
00390 )
00391 {
00392 #ifdef NSSDEBUG
00393   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
00394     return CK_FALSE;
00395   }
00396 #endif /* NSSDEBUG */
00397 
00398   return fwSession->rw;
00399 }
00400 
00401 /*
00402  * nssCKFWSession_IsSO
00403  *
00404  */
00405 NSS_IMPLEMENT CK_BBOOL
00406 nssCKFWSession_IsSO
00407 (
00408   NSSCKFWSession *fwSession
00409 )
00410 {
00411   CK_STATE state;
00412 
00413 #ifdef NSSDEBUG
00414   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
00415     return CK_FALSE;
00416   }
00417 #endif /* NSSDEBUG */
00418 
00419   state = nssCKFWToken_GetSessionState(fwSession->fwToken);
00420   switch( state ) {
00421   case CKS_RO_PUBLIC_SESSION:
00422   case CKS_RO_USER_FUNCTIONS:
00423   case CKS_RW_PUBLIC_SESSION:
00424   case CKS_RW_USER_FUNCTIONS:
00425     return CK_FALSE;
00426   case CKS_RW_SO_FUNCTIONS:
00427     return CK_TRUE;
00428   default:
00429     return CK_FALSE;
00430   }
00431 }
00432 
00433 /*
00434  * nssCKFWSession_GetFWSlot
00435  *
00436  */
00437 NSS_IMPLEMENT NSSCKFWSlot *
00438 nssCKFWSession_GetFWSlot
00439 (
00440   NSSCKFWSession *fwSession
00441 )
00442 {
00443 #ifdef NSSDEBUG
00444   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
00445     return (NSSCKFWSlot *)NULL;
00446   }
00447 #endif /* NSSDEBUG */
00448 
00449   return nssCKFWToken_GetFWSlot(fwSession->fwToken);
00450 }
00451 
00452 /*
00453  * nssCFKWSession_GetSessionState
00454  *
00455  */
00456 NSS_IMPLEMENT CK_STATE
00457 nssCKFWSession_GetSessionState
00458 (
00459   NSSCKFWSession *fwSession
00460 )
00461 {
00462 #ifdef NSSDEBUG
00463   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
00464     return CKS_RO_PUBLIC_SESSION; /* whatever */
00465   }
00466 #endif /* NSSDEBUG */
00467 
00468   return nssCKFWToken_GetSessionState(fwSession->fwToken);
00469 }
00470 
00471 /*
00472  * nssCKFWSession_SetFWFindObjects
00473  *
00474  */
00475 NSS_IMPLEMENT CK_RV
00476 nssCKFWSession_SetFWFindObjects
00477 (
00478   NSSCKFWSession *fwSession,
00479   NSSCKFWFindObjects *fwFindObjects
00480 )
00481 {
00482 #ifdef NSSDEBUG
00483   CK_RV error = CKR_OK;
00484 #endif /* NSSDEBUG */
00485 
00486 #ifdef NSSDEBUG
00487   error = nssCKFWSession_verifyPointer(fwSession);
00488   if( CKR_OK != error ) {
00489     return error;
00490   }
00491 
00492   /* fwFindObjects may be null */
00493 #endif /* NSSDEBUG */
00494 
00495   if( ((NSSCKFWFindObjects *)NULL != fwSession->fwFindObjects) &&
00496       ((NSSCKFWFindObjects *)NULL != fwFindObjects) ) {
00497     return CKR_OPERATION_ACTIVE;
00498   }
00499 
00500   fwSession->fwFindObjects = fwFindObjects;
00501 
00502   return CKR_OK;
00503 }
00504 
00505 /*
00506  * nssCKFWSession_GetFWFindObjects
00507  *
00508  */
00509 NSS_IMPLEMENT NSSCKFWFindObjects *
00510 nssCKFWSession_GetFWFindObjects
00511 (
00512   NSSCKFWSession *fwSession,
00513   CK_RV *pError
00514 )
00515 {
00516 #ifdef NSSDEBUG
00517   if( (CK_RV *)NULL == pError ) {
00518     return (NSSCKFWFindObjects *)NULL;
00519   }
00520 
00521   *pError = nssCKFWSession_verifyPointer(fwSession);
00522   if( CKR_OK != *pError ) {
00523     return (NSSCKFWFindObjects *)NULL;
00524   }
00525 #endif /* NSSDEBUG */
00526 
00527   if( (NSSCKFWFindObjects *)NULL == fwSession->fwFindObjects ) {
00528     *pError = CKR_OPERATION_NOT_INITIALIZED;
00529     return (NSSCKFWFindObjects *)NULL;
00530   }
00531 
00532   return fwSession->fwFindObjects;
00533 }
00534 
00535 /*
00536  * nssCKFWSession_SetMDSession
00537  *
00538  */
00539 NSS_IMPLEMENT CK_RV
00540 nssCKFWSession_SetMDSession
00541 (
00542   NSSCKFWSession *fwSession,
00543   NSSCKMDSession *mdSession
00544 )
00545 {
00546 #ifdef NSSDEBUG
00547   CK_RV error = CKR_OK;
00548 #endif /* NSSDEBUG */
00549 
00550 #ifdef NSSDEBUG
00551   error = nssCKFWSession_verifyPointer(fwSession);
00552   if( CKR_OK != error ) {
00553     return error;
00554   }
00555 
00556   if( (NSSCKMDSession *)NULL == mdSession ) {
00557     return CKR_ARGUMENTS_BAD;
00558   }
00559 #endif /* NSSDEBUG */
00560 
00561   if( (NSSCKMDSession *)NULL != fwSession->mdSession ) {
00562     return CKR_GENERAL_ERROR;
00563   }
00564 
00565   fwSession->mdSession = mdSession;
00566 
00567   return CKR_OK;
00568 }
00569 
00570 /*
00571  * nssCKFWSession_SetHandle
00572  *
00573  */
00574 NSS_IMPLEMENT CK_RV
00575 nssCKFWSession_SetHandle
00576 (
00577   NSSCKFWSession *fwSession,
00578   CK_SESSION_HANDLE hSession
00579 )
00580 {
00581 #ifdef NSSDEBUG
00582   CK_RV error = CKR_OK;
00583 #endif /* NSSDEBUG */
00584 
00585 #ifdef NSSDEBUG
00586   error = nssCKFWSession_verifyPointer(fwSession);
00587   if( CKR_OK != error ) {
00588     return error;
00589   }
00590 #endif /* NSSDEBUG */
00591 
00592   if( (CK_SESSION_HANDLE)0 != fwSession->hSession ) {
00593     return CKR_GENERAL_ERROR;
00594   }
00595 
00596   fwSession->hSession = hSession;
00597 
00598   return CKR_OK;
00599 }
00600 
00601 /*
00602  * nssCKFWSession_GetHandle
00603  *
00604  */
00605 NSS_IMPLEMENT CK_SESSION_HANDLE
00606 nssCKFWSession_GetHandle
00607 (
00608   NSSCKFWSession *fwSession
00609 )
00610 {
00611 #ifdef NSSDEBUG
00612   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
00613     return NULL;
00614   }
00615 #endif /* NSSDEBUG */
00616 
00617   return fwSession->hSession;
00618 }
00619 
00620 /*
00621  * nssCKFWSession_RegisterSessionObject
00622  *
00623  */
00624 NSS_IMPLEMENT CK_RV
00625 nssCKFWSession_RegisterSessionObject
00626 (
00627   NSSCKFWSession *fwSession,
00628   NSSCKFWObject *fwObject
00629 )
00630 {
00631   CK_RV rv = CKR_OK;
00632 
00633 #ifdef NSSDEBUG
00634   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
00635     return CKR_GENERAL_ERROR;
00636   }
00637 #endif /* NSSDEBUG */
00638 
00639   if( (nssCKFWHash *)NULL != fwSession->sessionObjectHash ) {
00640     rv = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject);
00641   }
00642 
00643   return rv;
00644 }
00645 
00646 /*
00647  * nssCKFWSession_DeregisterSessionObject
00648  *
00649  */
00650 NSS_IMPLEMENT CK_RV
00651 nssCKFWSession_DeregisterSessionObject
00652 (
00653   NSSCKFWSession *fwSession,
00654   NSSCKFWObject *fwObject
00655 )
00656 {
00657 #ifdef NSSDEBUG
00658   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
00659     return CKR_GENERAL_ERROR;
00660   }
00661 #endif /* NSSDEBUG */
00662 
00663   if( (nssCKFWHash *)NULL != fwSession->sessionObjectHash ) {
00664     nssCKFWHash_Remove(fwSession->sessionObjectHash, fwObject);
00665   }
00666 
00667   return CKR_OK;
00668 }
00669 
00670 /*
00671  * nssCKFWSession_GetDeviceError
00672  *
00673  */
00674 NSS_IMPLEMENT CK_ULONG
00675 nssCKFWSession_GetDeviceError
00676 (
00677   NSSCKFWSession *fwSession
00678 )
00679 {
00680 #ifdef NSSDEBUG
00681   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
00682     return (CK_ULONG)0;
00683   }
00684 
00685   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
00686     return (CK_ULONG)0;
00687   }
00688 #endif /* NSSDEBUG */
00689 
00690   if( (void *)NULL == (void *)fwSession->mdSession->GetDeviceError ) {
00691     return (CK_ULONG)0;
00692   }
00693 
00694   return fwSession->mdSession->GetDeviceError(fwSession->mdSession, 
00695     fwSession, fwSession->mdToken, fwSession->fwToken, 
00696     fwSession->mdInstance, fwSession->fwInstance);
00697 }
00698 
00699 /*
00700  * nssCKFWSession_Login
00701  *
00702  */
00703 NSS_IMPLEMENT CK_RV
00704 nssCKFWSession_Login
00705 (
00706   NSSCKFWSession *fwSession,
00707   CK_USER_TYPE userType,
00708   NSSItem *pin
00709 )
00710 {
00711   CK_RV error = CKR_OK;
00712   CK_STATE oldState;
00713   CK_STATE newState;
00714 
00715 #ifdef NSSDEBUG
00716   error = nssCKFWSession_verifyPointer(fwSession);
00717   if( CKR_OK != error ) {
00718     return error;
00719   }
00720 
00721   switch( userType ) {
00722   case CKU_SO:
00723   case CKU_USER:
00724     break;
00725   default:
00726     return CKR_USER_TYPE_INVALID;
00727   }
00728 
00729   if( (NSSItem *)NULL == pin ) {
00730     if( CK_TRUE != nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken) ) {
00731       return CKR_ARGUMENTS_BAD;
00732     }
00733   }
00734 
00735   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
00736     return CKR_GENERAL_ERROR;
00737   }
00738 #endif /* NSSDEBUG */
00739 
00740   oldState = nssCKFWToken_GetSessionState(fwSession->fwToken);
00741 
00742   /*
00743    * It's not clear what happens when you're already logged in.
00744    * I'll just fail; but if we decide to change, the logic is
00745    * all right here.
00746    */
00747 
00748   if( CKU_SO == userType ) {
00749     switch( oldState ) {
00750     case CKS_RO_PUBLIC_SESSION:      
00751       /*
00752        * There's no such thing as a read-only security officer
00753        * session, so fail.  The error should be CKR_SESSION_READ_ONLY,
00754        * except that C_Login isn't defined to return that.  So we'll
00755        * do CKR_SESSION_READ_ONLY_EXISTS, which is what is documented.
00756        */
00757       return CKR_SESSION_READ_ONLY_EXISTS;
00758     case CKS_RO_USER_FUNCTIONS:
00759       return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
00760     case CKS_RW_PUBLIC_SESSION:
00761       newState = CKS_RW_SO_FUNCTIONS;
00762       break;
00763     case CKS_RW_USER_FUNCTIONS:
00764       return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
00765     case CKS_RW_SO_FUNCTIONS:
00766       return CKR_USER_ALREADY_LOGGED_IN;
00767     default:
00768       return CKR_GENERAL_ERROR;
00769     }
00770   } else /* CKU_USER == userType */ {
00771     switch( oldState ) {
00772     case CKS_RO_PUBLIC_SESSION:      
00773       newState = CKS_RO_USER_FUNCTIONS;
00774       break;
00775     case CKS_RO_USER_FUNCTIONS:
00776       return CKR_USER_ALREADY_LOGGED_IN;
00777     case CKS_RW_PUBLIC_SESSION:
00778       newState = CKS_RW_USER_FUNCTIONS;
00779       break;
00780     case CKS_RW_USER_FUNCTIONS:
00781       return CKR_USER_ALREADY_LOGGED_IN;
00782     case CKS_RW_SO_FUNCTIONS:
00783       return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
00784     default:
00785       return CKR_GENERAL_ERROR;
00786     }
00787   }
00788 
00789   /*
00790    * So now we're in one of three cases:
00791    *
00792    * Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_SO_FUNCTIONS;
00793    * Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_USER_FUNCTIONS;
00794    * Old == CKS_RO_PUBLIC_SESSION, New == CKS_RO_USER_FUNCTIONS;
00795    */
00796 
00797   if( (void *)NULL == (void *)fwSession->mdSession->Login ) {
00798     /*
00799      * The Module doesn't want to be informed (or check the pin)
00800      * it'll just rely on the Framework as needed.
00801      */
00802     ;
00803   } else {
00804     error = fwSession->mdSession->Login(fwSession->mdSession, fwSession,
00805       fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
00806       fwSession->fwInstance, userType, pin, oldState, newState);
00807     if( CKR_OK != error ) {
00808       return error;
00809     }
00810   }
00811 
00812   (void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState);
00813   return CKR_OK;
00814 }
00815 
00816 /*
00817  * nssCKFWSession_Logout
00818  *
00819  */
00820 NSS_IMPLEMENT CK_RV
00821 nssCKFWSession_Logout
00822 (
00823   NSSCKFWSession *fwSession
00824 )
00825 {
00826   CK_RV error = CKR_OK;
00827   CK_STATE oldState;
00828   CK_STATE newState;
00829 
00830 #ifdef NSSDEBUG
00831   error = nssCKFWSession_verifyPointer(fwSession);
00832   if( CKR_OK != error ) {
00833     return error;
00834   }
00835 
00836   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
00837     return CKR_GENERAL_ERROR;
00838   }
00839 #endif /* NSSDEBUG */
00840 
00841   oldState = nssCKFWToken_GetSessionState(fwSession->fwToken);
00842 
00843   switch( oldState ) {
00844   case CKS_RO_PUBLIC_SESSION:
00845     return CKR_USER_NOT_LOGGED_IN;
00846   case CKS_RO_USER_FUNCTIONS:
00847     newState = CKS_RO_PUBLIC_SESSION;
00848     break;
00849   case CKS_RW_PUBLIC_SESSION:
00850     return CKR_USER_NOT_LOGGED_IN;
00851   case CKS_RW_USER_FUNCTIONS:
00852     newState = CKS_RW_PUBLIC_SESSION;
00853     break;
00854   case CKS_RW_SO_FUNCTIONS:
00855     newState = CKS_RW_PUBLIC_SESSION;
00856     break;
00857   default:
00858     return CKR_GENERAL_ERROR;
00859   }
00860 
00861   /*
00862    * So now we're in one of three cases:
00863    *
00864    * Old == CKS_RW_SO_FUNCTIONS,   New == CKS_RW_PUBLIC_SESSION;
00865    * Old == CKS_RW_USER_FUNCTIONS, New == CKS_RW_PUBLIC_SESSION;
00866    * Old == CKS_RO_USER_FUNCTIONS, New == CKS_RO_PUBLIC_SESSION;
00867    */
00868 
00869   if( (void *)NULL == (void *)fwSession->mdSession->Logout ) {
00870     /*
00871      * The Module doesn't want to be informed.  Okay.
00872      */
00873     ;
00874   } else {
00875     error = fwSession->mdSession->Logout(fwSession->mdSession, fwSession,
00876       fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
00877       fwSession->fwInstance, oldState, newState);
00878     if( CKR_OK != error ) {
00879       /*
00880        * Now what?!  A failure really should end up with the Framework
00881        * considering it logged out, right?
00882        */
00883       ;
00884     }
00885   }
00886 
00887   (void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState);
00888   return error;
00889 }
00890 
00891 /*
00892  * nssCKFWSession_InitPIN
00893  *
00894  */
00895 NSS_IMPLEMENT CK_RV
00896 nssCKFWSession_InitPIN
00897 (
00898   NSSCKFWSession *fwSession,
00899   NSSItem *pin
00900 )
00901 {
00902   CK_RV error = CKR_OK;
00903   CK_STATE state;
00904 
00905 #ifdef NSSDEBUG
00906   error = nssCKFWSession_verifyPointer(fwSession);
00907   if( CKR_OK != error ) {
00908     return error;
00909   }
00910 
00911   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
00912     return CKR_GENERAL_ERROR;
00913   }
00914 #endif /* NSSDEBUG */
00915 
00916   state = nssCKFWToken_GetSessionState(fwSession->fwToken);
00917   if( CKS_RW_SO_FUNCTIONS != state ) {
00918     return CKR_USER_NOT_LOGGED_IN;
00919   }
00920 
00921   if( (NSSItem *)NULL == pin ) {
00922     CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
00923     if( CK_TRUE != has ) {
00924       return CKR_ARGUMENTS_BAD;
00925     }
00926   }
00927 
00928   if( (void *)NULL == (void *)fwSession->mdSession->InitPIN ) {
00929     return CKR_TOKEN_WRITE_PROTECTED;
00930   }
00931 
00932   error = fwSession->mdSession->InitPIN(fwSession->mdSession, fwSession,
00933     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
00934     fwSession->fwInstance, pin);
00935 
00936   return error;
00937 }
00938 
00939 /*
00940  * nssCKFWSession_SetPIN
00941  *
00942  */
00943 NSS_IMPLEMENT CK_RV
00944 nssCKFWSession_SetPIN
00945 (
00946   NSSCKFWSession *fwSession,
00947   NSSItem *newPin,
00948   NSSItem *oldPin
00949 )
00950 {
00951   CK_RV error = CKR_OK;
00952   CK_STATE state;
00953 
00954 #ifdef NSSDEBUG
00955   error = nssCKFWSession_verifyPointer(fwSession);
00956   if( CKR_OK != error ) {
00957     return error;
00958   }
00959 
00960   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
00961     return CKR_GENERAL_ERROR;
00962   }
00963 #endif /* NSSDEBUG */
00964 
00965   state = nssCKFWToken_GetSessionState(fwSession->fwToken);
00966   if( (CKS_RW_SO_FUNCTIONS != state) &&
00967       (CKS_RW_USER_FUNCTIONS != state) ) {
00968     return CKR_USER_NOT_LOGGED_IN;
00969   }
00970 
00971   if( (NSSItem *)NULL == newPin ) {
00972     CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
00973     if( CK_TRUE != has ) {
00974       return CKR_ARGUMENTS_BAD;
00975     }
00976   }
00977 
00978   if( (NSSItem *)NULL == oldPin ) {
00979     CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
00980     if( CK_TRUE != has ) {
00981       return CKR_ARGUMENTS_BAD;
00982     }
00983   }
00984 
00985   if( (void *)NULL == (void *)fwSession->mdSession->SetPIN ) {
00986     return CKR_TOKEN_WRITE_PROTECTED;
00987   }
00988 
00989   error = fwSession->mdSession->SetPIN(fwSession->mdSession, fwSession,
00990     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
00991     fwSession->fwInstance, newPin, oldPin);
00992 
00993   return error;
00994 }
00995 
00996 /*
00997  * nssCKFWSession_GetOperationStateLen
00998  *
00999  */
01000 NSS_IMPLEMENT CK_ULONG
01001 nssCKFWSession_GetOperationStateLen
01002 (
01003   NSSCKFWSession *fwSession,
01004   CK_RV *pError
01005 )
01006 {
01007   CK_ULONG mdAmt;
01008   CK_ULONG fwAmt;
01009 
01010 #ifdef NSSDEBUG
01011   if( (CK_RV *)NULL == pError ) {
01012     return (CK_ULONG)0;
01013   }
01014 
01015   *pError = nssCKFWSession_verifyPointer(fwSession);
01016   if( CKR_OK != *pError ) {
01017     return (CK_ULONG)0;
01018   }
01019 
01020   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
01021     *pError = CKR_GENERAL_ERROR;
01022     return (CK_ULONG)0;
01023   }
01024 #endif /* NSSDEBUG */
01025 
01026   if( (void *)NULL == (void *)fwSession->mdSession->GetOperationStateLen ) {
01027     *pError = CKR_STATE_UNSAVEABLE;
01028   }
01029 
01030   /*
01031    * We could check that the session is actually in some state..
01032    */
01033 
01034   mdAmt = fwSession->mdSession->GetOperationStateLen(fwSession->mdSession,
01035     fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
01036     fwSession->fwInstance, pError);
01037 
01038   if( ((CK_ULONG)0 == mdAmt) && (CKR_OK != *pError) ) {
01039     return (CK_ULONG)0;
01040   }
01041 
01042   /*
01043    * Add a bit of sanity-checking
01044    */
01045   fwAmt = mdAmt + 2*sizeof(CK_ULONG);
01046 
01047   return fwAmt;
01048 }
01049 
01050 /*
01051  * nssCKFWSession_GetOperationState
01052  *
01053  */
01054 NSS_IMPLEMENT CK_RV
01055 nssCKFWSession_GetOperationState
01056 (
01057   NSSCKFWSession *fwSession,
01058   NSSItem *buffer
01059 )
01060 {
01061   CK_RV error = CKR_OK;
01062   CK_ULONG fwAmt;
01063   CK_ULONG *ulBuffer;
01064   NSSItem i2;
01065   CK_ULONG n, i;
01066 
01067 #ifdef NSSDEBUG
01068   error = nssCKFWSession_verifyPointer(fwSession);
01069   if( CKR_OK != error ) {
01070     return error;
01071   }
01072 
01073   if( (NSSItem *)NULL == buffer ) {
01074     return CKR_ARGUMENTS_BAD;
01075   }
01076 
01077   if( (void *)NULL == buffer->data ) {
01078     return CKR_ARGUMENTS_BAD;
01079   }
01080 
01081   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
01082     return CKR_GENERAL_ERROR;
01083   }
01084 #endif /* NSSDEBUG */
01085 
01086   if( (void *)NULL == (void *)fwSession->mdSession->GetOperationState ) {
01087     return CKR_STATE_UNSAVEABLE;
01088   }
01089 
01090   /*
01091    * Sanity-check the caller's buffer.
01092    */
01093 
01094   error = CKR_OK;
01095   fwAmt = nssCKFWSession_GetOperationStateLen(fwSession, &error);
01096   if( ((CK_ULONG)0 == fwAmt) && (CKR_OK != error) ) {
01097     return error;
01098   }
01099 
01100   if( buffer->size < fwAmt ) {
01101     return CKR_BUFFER_TOO_SMALL;
01102   }
01103 
01104   ulBuffer = (CK_ULONG *)buffer->data;
01105 
01106   i2.size = buffer->size - 2*sizeof(CK_ULONG);
01107   i2.data = (void *)&ulBuffer[2];
01108 
01109   error = fwSession->mdSession->GetOperationState(fwSession->mdSession,
01110     fwSession, fwSession->mdToken, fwSession->fwToken, 
01111     fwSession->mdInstance, fwSession->fwInstance, &i2);
01112 
01113   if( CKR_OK != error ) {
01114     return error;
01115   }
01116 
01117   /*
01118    * Add a little integrety/identity check.  
01119    * NOTE: right now, it's pretty stupid.  
01120    * A CRC or something would be better.
01121    */
01122 
01123   ulBuffer[0] = 0x434b4657; /* CKFW */
01124   ulBuffer[1] = 0;
01125   n = i2.size/sizeof(CK_ULONG);
01126   for( i = 0; i < n; i++ ) {
01127     ulBuffer[1] ^= ulBuffer[2+i];
01128   }
01129 
01130   return CKR_OK;
01131 }
01132 
01133 /*
01134  * nssCKFWSession_SetOperationState
01135  *
01136  */
01137 NSS_IMPLEMENT CK_RV
01138 nssCKFWSession_SetOperationState
01139 (
01140   NSSCKFWSession *fwSession,
01141   NSSItem *state,
01142   NSSCKFWObject *encryptionKey,
01143   NSSCKFWObject *authenticationKey
01144 )
01145 {
01146   CK_RV error = CKR_OK;
01147   CK_ULONG *ulBuffer;
01148   CK_ULONG n, i;
01149   CK_ULONG x;
01150   NSSItem s;
01151   NSSCKMDObject *mdek;
01152   NSSCKMDObject *mdak;
01153 
01154 #ifdef NSSDEBUG
01155   error = nssCKFWSession_verifyPointer(fwSession);
01156   if( CKR_OK != error ) {
01157     return error;
01158   }
01159 
01160   if( (NSSItem *)NULL == state ) {
01161     return CKR_ARGUMENTS_BAD;
01162   }
01163 
01164   if( (void *)NULL == state->data ) {
01165     return CKR_ARGUMENTS_BAD;
01166   }
01167 
01168   if( (NSSCKFWObject *)NULL != encryptionKey ) {
01169     error = nssCKFWObject_verifyPointer(encryptionKey);
01170     if( CKR_OK != error ) {
01171       return error;
01172     }
01173   }
01174 
01175   if( (NSSCKFWObject *)NULL != authenticationKey ) {
01176     error = nssCKFWObject_verifyPointer(authenticationKey);
01177     if( CKR_OK != error ) {
01178       return error;
01179     }
01180   }
01181 
01182   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
01183     return CKR_GENERAL_ERROR;
01184   }
01185 #endif /* NSSDEBUG */
01186 
01187   ulBuffer = (CK_ULONG *)state->data;
01188   if( 0x43b4657 != ulBuffer[0] ) {
01189     return CKR_SAVED_STATE_INVALID;
01190   }
01191   n = (state->size / sizeof(CK_ULONG)) - 2;
01192   x = (CK_ULONG)0;
01193   for( i = 0; i < n; i++ ) {
01194     x ^= ulBuffer[2+i];
01195   }
01196 
01197   if( x != ulBuffer[1] ) {
01198     return CKR_SAVED_STATE_INVALID;
01199   }
01200 
01201   if( (void *)NULL == (void *)fwSession->mdSession->SetOperationState ) {
01202     return CKR_GENERAL_ERROR;
01203   }
01204 
01205   s.size = state->size - 2*sizeof(CK_ULONG);
01206   s.data = (void *)&ulBuffer[2];
01207 
01208   if( (NSSCKFWObject *)NULL != encryptionKey ) {
01209     mdek = nssCKFWObject_GetMDObject(encryptionKey);
01210   } else {
01211     mdek = (NSSCKMDObject *)NULL;
01212   }
01213 
01214   if( (NSSCKFWObject *)NULL != authenticationKey ) {
01215     mdak = nssCKFWObject_GetMDObject(authenticationKey);
01216   } else {
01217     mdak = (NSSCKMDObject *)NULL;
01218   }
01219 
01220   error = fwSession->mdSession->SetOperationState(fwSession->mdSession, 
01221     fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
01222     fwSession->fwInstance, &s, mdek, encryptionKey, mdak, authenticationKey);
01223 
01224   if( CKR_OK != error ) {
01225     return error;
01226   }
01227 
01228   /*
01229    * Here'd we restore any session data
01230    */
01231   
01232   return CKR_OK;
01233 }
01234 
01235 static CK_BBOOL
01236 nss_attributes_form_token_object
01237 (
01238   CK_ATTRIBUTE_PTR pTemplate,
01239   CK_ULONG ulAttributeCount
01240 )
01241 {
01242   CK_ULONG i;
01243   CK_BBOOL rv;
01244 
01245   for( i = 0; i < ulAttributeCount; i++ ) {
01246     if( CKA_TOKEN == pTemplate[i].type ) {
01247       /* If we sanity-check, we can remove this sizeof check */
01248       if( sizeof(CK_BBOOL) == pTemplate[i].ulValueLen ) {
01249         (void)nsslibc_memcpy(&rv, pTemplate[i].pValue, sizeof(CK_BBOOL));
01250         return rv;
01251       } else {
01252         return CK_FALSE;
01253       }
01254     }
01255   }
01256 
01257   return CK_FALSE;
01258 }
01259 
01260 /*
01261  * nssCKFWSession_CreateObject
01262  *
01263  */
01264 NSS_IMPLEMENT NSSCKFWObject *
01265 nssCKFWSession_CreateObject
01266 (
01267   NSSCKFWSession *fwSession,
01268   CK_ATTRIBUTE_PTR pTemplate,
01269   CK_ULONG ulAttributeCount,
01270   CK_RV *pError
01271 )
01272 {
01273   NSSArena *arena;
01274   NSSCKMDObject *mdObject;
01275   NSSCKFWObject *fwObject;
01276   CK_BBOOL isTokenObject;
01277 
01278 #ifdef NSSDEBUG
01279   if( (CK_RV *)NULL == pError ) {
01280     return (NSSCKFWObject *)NULL;
01281   }
01282 
01283   *pError = nssCKFWSession_verifyPointer(fwSession);
01284   if( CKR_OK != pError ) {
01285     return (NSSCKFWObject *)NULL;
01286   }
01287 
01288   if( (CK_ATTRIBUTE_PTR)NULL == pTemplate ) {
01289     *pError = CKR_ARGUMENTS_BAD;
01290     return (NSSCKFWObject *)NULL;
01291   }
01292 
01293   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
01294     *pError = CKR_GENERAL_ERROR;
01295     return (NSSCKFWObject *)NULL;
01296   }
01297 #endif /* NSSDEBUG */
01298 
01299   /*
01300    * Here would be an excellent place to sanity-check the object.
01301    */
01302 
01303   isTokenObject = nss_attributes_form_token_object(pTemplate, ulAttributeCount);
01304   if( CK_TRUE == isTokenObject ) {
01305     /* === TOKEN OBJECT === */
01306 
01307     if( (void *)NULL == (void *)fwSession->mdSession->CreateObject ) {
01308       *pError = CKR_TOKEN_WRITE_PROTECTED;
01309       return (NSSCKFWObject *)NULL;
01310     }
01311 
01312     arena = nssCKFWToken_GetArena(fwSession->fwToken, pError);
01313     if( (NSSArena *)NULL == arena ) {
01314       if( CKR_OK == *pError ) {
01315         *pError = CKR_GENERAL_ERROR;
01316       }
01317       return (NSSCKFWObject *)NULL;
01318     }
01319 
01320     goto callmdcreateobject;
01321   } else {
01322     /* === SESSION OBJECT === */
01323 
01324     arena = nssCKFWSession_GetArena(fwSession, pError);
01325     if( (NSSArena *)NULL == arena ) {
01326       if( CKR_OK == *pError ) {
01327         *pError = CKR_GENERAL_ERROR;
01328       }
01329       return (NSSCKFWObject *)NULL;
01330     }
01331 
01332     if( CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects(
01333                      fwSession->fwInstance) ) {
01334       /* --- module handles the session object -- */
01335 
01336       if( (void *)NULL == (void *)fwSession->mdSession->CreateObject ) {
01337         *pError = CKR_GENERAL_ERROR;
01338         return (NSSCKFWObject *)NULL;
01339       }
01340       
01341       goto callmdcreateobject;
01342     } else {
01343       /* --- framework handles the session object -- */
01344       mdObject = nssCKMDSessionObject_Create(fwSession->fwToken, 
01345         arena, pTemplate, ulAttributeCount, pError);
01346       goto gotmdobject;
01347     }
01348   }
01349 
01350  callmdcreateobject:
01351   mdObject = fwSession->mdSession->CreateObject(fwSession->mdSession,
01352     fwSession, fwSession->mdToken, fwSession->fwToken,
01353     fwSession->mdInstance, fwSession->fwInstance, arena, pTemplate,
01354     ulAttributeCount, pError);
01355 
01356  gotmdobject:
01357   if( (NSSCKMDObject *)NULL == mdObject ) {
01358     if( CKR_OK == *pError ) {
01359       *pError = CKR_GENERAL_ERROR;
01360     }
01361     return (NSSCKFWObject *)NULL;
01362   }
01363 
01364   fwObject = nssCKFWObject_Create(arena, mdObject, fwSession, 
01365     fwSession->fwToken, fwSession->fwInstance, pError);
01366   if( (NSSCKFWObject *)NULL == fwObject ) {
01367     if( CKR_OK == *pError ) {
01368       *pError = CKR_GENERAL_ERROR;
01369     }
01370     
01371     if( (void *)NULL != (void *)mdObject->Destroy ) {
01372       (void)mdObject->Destroy(mdObject, (NSSCKFWObject *)NULL,
01373         fwSession->mdSession, fwSession, fwSession->mdToken,
01374         fwSession->fwToken, fwSession->mdInstance, fwSession->fwInstance);
01375     }
01376     
01377     return (NSSCKFWObject *)NULL;
01378   }
01379 
01380   if( CK_FALSE == isTokenObject ) {
01381     if( CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, fwObject) ) {
01382       *pError = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject);
01383       if( CKR_OK != *pError ) {
01384         nssCKFWObject_Finalize(fwObject);
01385         return (NSSCKFWObject *)NULL;
01386       }
01387     }
01388   }
01389   
01390   return fwObject;
01391 }
01392 
01393 /*
01394  * nssCKFWSession_CopyObject
01395  *
01396  */
01397 NSS_IMPLEMENT NSSCKFWObject *
01398 nssCKFWSession_CopyObject
01399 (
01400   NSSCKFWSession *fwSession,
01401   NSSCKFWObject *fwObject,
01402   CK_ATTRIBUTE_PTR pTemplate,
01403   CK_ULONG ulAttributeCount,
01404   CK_RV *pError
01405 )
01406 {
01407   CK_BBOOL oldIsToken;
01408   CK_BBOOL newIsToken;
01409   CK_ULONG i;
01410   NSSCKFWObject *rv;
01411 
01412 #ifdef NSSDEBUG
01413   if( (CK_RV *)NULL == pError ) {
01414     return (NSSCKFWObject *)NULL;
01415   }
01416 
01417   *pError = nssCKFWSession_verifyPointer(fwSession);
01418   if( CKR_OK != *pError ) {
01419     return (NSSCKFWObject *)NULL;
01420   }
01421 
01422   *pError = nssCKFWObject_verifyPointer(fwObject);
01423   if( CKR_OK != *pError ) {
01424     return (NSSCKFWObject *)NULL;
01425   }
01426 
01427   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
01428     *pError = CKR_GENERAL_ERROR;
01429     return (NSSCKFWObject *)NULL;
01430   }
01431 #endif /* NSSDEBUG */
01432 
01433   /*
01434    * Sanity-check object
01435    */
01436 
01437   oldIsToken = nssCKFWObject_IsTokenObject(fwObject);
01438 
01439   newIsToken = oldIsToken;
01440   for( i = 0; i < ulAttributeCount; i++ ) {
01441     if( CKA_TOKEN == pTemplate[i].type ) {
01442       /* Since we sanity-checked the object, we know this is the right size. */
01443       (void)nsslibc_memcpy(&newIsToken, pTemplate[i].pValue, sizeof(CK_BBOOL));
01444       break;
01445     }
01446   }
01447 
01448   /*
01449    * If the Module handles its session objects, or if both the new
01450    * and old object are token objects, use CopyObject if it exists.
01451    */
01452 
01453   if( ((void *)NULL != (void *)fwSession->mdSession->CopyObject) &&
01454       (((CK_TRUE == oldIsToken) && (CK_TRUE == newIsToken)) ||
01455        (CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects(
01456                      fwSession->fwInstance))) ) {
01457     /* use copy object */
01458     NSSArena *arena;
01459     NSSCKMDObject *mdOldObject;
01460     NSSCKMDObject *mdObject;
01461 
01462     mdOldObject = nssCKFWObject_GetMDObject(fwObject);
01463 
01464     if( CK_TRUE == newIsToken ) {
01465       arena = nssCKFWToken_GetArena(fwSession->fwToken, pError);
01466     } else {
01467       arena = nssCKFWSession_GetArena(fwSession, pError);
01468     }
01469     if( (NSSArena *)NULL == arena ) {
01470       if( CKR_OK == *pError ) {
01471         *pError = CKR_GENERAL_ERROR;
01472       }
01473       return (NSSCKFWObject *)NULL;
01474     }
01475 
01476     mdObject = fwSession->mdSession->CopyObject(fwSession->mdSession,
01477       fwSession, fwSession->mdToken, fwSession->fwToken,
01478       fwSession->mdInstance, fwSession->fwInstance, mdOldObject,
01479       fwObject, arena, pTemplate, ulAttributeCount, pError);
01480     if( (NSSCKMDObject *)NULL == mdObject ) {
01481       if( CKR_OK == *pError ) {
01482         *pError = CKR_GENERAL_ERROR;
01483       }
01484       return (NSSCKFWObject *)NULL;
01485     }
01486 
01487     rv = nssCKFWObject_Create(arena, mdObject, fwSession,
01488       fwSession->fwToken, fwSession->fwInstance, pError);
01489     if( (NSSCKFWObject *)NULL == fwObject ) {
01490       if( CKR_OK == *pError ) {
01491         *pError = CKR_GENERAL_ERROR;
01492       }
01493 
01494       if( (void *)NULL != (void *)mdObject->Destroy ) {
01495         (void)mdObject->Destroy(mdObject, (NSSCKFWObject *)NULL,
01496           fwSession->mdSession, fwSession, fwSession->mdToken,
01497           fwSession->fwToken, fwSession->mdInstance, fwSession->fwInstance);
01498       }
01499     
01500       return (NSSCKFWObject *)NULL;
01501     }
01502 
01503     if( CK_FALSE == newIsToken ) {
01504       if( CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, rv) ) {
01505         *pError = nssCKFWHash_Add(fwSession->sessionObjectHash, rv, rv);
01506         if( CKR_OK != *pError ) {
01507           nssCKFWObject_Finalize(rv);
01508           return (NSSCKFWObject *)NULL;
01509         }
01510       }
01511     }
01512 
01513     return rv;
01514   } else {
01515     /* use create object */
01516     NSSArena *tmpArena;
01517     CK_ATTRIBUTE_PTR newTemplate;
01518     CK_ULONG i, j, n, newLength, k;
01519     CK_ATTRIBUTE_TYPE_PTR oldTypes;
01520     NSSCKFWObject *rv;
01521     
01522     tmpArena = NSSArena_Create();
01523     if( (NSSArena *)NULL == tmpArena ) {
01524       *pError = CKR_HOST_MEMORY;
01525       return (NSSCKFWObject *)NULL;
01526     }
01527 
01528     n = nssCKFWObject_GetAttributeCount(fwObject, pError);
01529     if( (0 == n) && (CKR_OK != *pError) ) {
01530       return (NSSCKFWObject *)NULL;
01531     }
01532 
01533     oldTypes = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE_TYPE, n);
01534     if( (CK_ATTRIBUTE_TYPE_PTR)NULL == oldTypes ) {
01535       NSSArena_Destroy(tmpArena);
01536       *pError = CKR_HOST_MEMORY;
01537       return (NSSCKFWObject *)NULL;
01538     }
01539 
01540     *pError = nssCKFWObject_GetAttributeTypes(fwObject, oldTypes, n);
01541     if( CKR_OK != *pError ) {
01542       NSSArena_Destroy(tmpArena);
01543       return (NSSCKFWObject *)NULL;
01544     }
01545 
01546     newLength = n;
01547     for( i = 0; i < ulAttributeCount; i++ ) {
01548       for( j = 0; j < n; j++ ) {
01549         if( oldTypes[j] == pTemplate[i].type ) {
01550           if( (CK_VOID_PTR)NULL == pTemplate[i].pValue ) {
01551             /* Removing the attribute */
01552             newLength--;
01553           }
01554           break;
01555         }
01556       }
01557       if( j == n ) {
01558         /* Not found */
01559         newLength++;
01560       }
01561     }
01562 
01563     newTemplate = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE, newLength);
01564     if( (CK_ATTRIBUTE_PTR)NULL == newTemplate ) {
01565       NSSArena_Destroy(tmpArena);
01566       *pError = CKR_HOST_MEMORY;
01567       return (NSSCKFWObject *)NULL;
01568     }
01569 
01570     k = 0;
01571     for( j = 0; j < n; j++ ) {
01572       for( i = 0; i < ulAttributeCount; i++ ) {
01573         if( oldTypes[j] == pTemplate[i].type ) {
01574           if( (CK_VOID_PTR)NULL == pTemplate[i].pValue ) {
01575             /* This attribute is being deleted */
01576             ;
01577           } else {
01578             /* This attribute is being replaced */
01579             newTemplate[k].type = pTemplate[i].type;
01580             newTemplate[k].pValue = pTemplate[i].pValue;
01581             newTemplate[k].ulValueLen = pTemplate[i].ulValueLen;
01582             k++;
01583           }
01584           break;
01585         }
01586       }
01587       if( i == ulAttributeCount ) {
01588         /* This attribute is being copied over from the old object */
01589         NSSItem item, *it;
01590         item.size = 0;
01591         item.data = (void *)NULL;
01592         it = nssCKFWObject_GetAttribute(fwObject, oldTypes[j],
01593           &item, tmpArena, pError);
01594         if( (NSSItem *)NULL == it ) {
01595           if( CKR_OK == *pError ) {
01596             *pError = CKR_GENERAL_ERROR;
01597           }
01598           NSSArena_Destroy(tmpArena);
01599           return (NSSCKFWObject *)NULL;
01600         }
01601         newTemplate[k].type = oldTypes[j];
01602         newTemplate[k].pValue = it->data;
01603         newTemplate[k].ulValueLen = it->size;
01604         k++;
01605       }
01606     }
01607     /* assert that k == newLength */
01608 
01609     rv = nssCKFWSession_CreateObject(fwSession, newTemplate, newLength, pError);
01610     if( (NSSCKFWObject *)NULL == rv ) {
01611       if( CKR_OK == *pError ) {
01612         *pError = CKR_GENERAL_ERROR;
01613       }
01614       NSSArena_Destroy(tmpArena);
01615       return (NSSCKFWObject *)NULL;
01616     }
01617 
01618     NSSArena_Destroy(tmpArena);
01619     return rv;
01620   }
01621 }
01622 
01623 /*
01624  * nssCKFWSession_FindObjectsInit
01625  *
01626  */
01627 NSS_IMPLEMENT NSSCKFWFindObjects *
01628 nssCKFWSession_FindObjectsInit
01629 (
01630   NSSCKFWSession *fwSession,
01631   CK_ATTRIBUTE_PTR pTemplate,
01632   CK_ULONG ulAttributeCount,
01633   CK_RV *pError
01634 )
01635 {
01636   NSSCKMDFindObjects *mdfo1 = (NSSCKMDFindObjects *)NULL;
01637   NSSCKMDFindObjects *mdfo2 = (NSSCKMDFindObjects *)NULL;
01638 
01639 #ifdef NSSDEBUG
01640   if( (CK_RV *)NULL == pError ) {
01641     return (NSSCKFWFindObjects *)NULL;
01642   }
01643 
01644   *pError = nssCKFWSession_verifyPointer(fwSession);
01645   if( CKR_OK != *pError ) {
01646     return (NSSCKFWFindObjects *)NULL;
01647   }
01648 
01649   if( ((CK_ATTRIBUTE_PTR)NULL == pTemplate) && (ulAttributeCount != 0) ) {
01650     *pError = CKR_ARGUMENTS_BAD;
01651     return (NSSCKFWFindObjects *)NULL;
01652   }
01653 
01654   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
01655     *pError = CKR_GENERAL_ERROR;
01656     return (NSSCKFWFindObjects *)NULL;
01657   }
01658 #endif /* NSSDEBUG */
01659 
01660   if( CK_TRUE != nssCKFWInstance_GetModuleHandlesSessionObjects(
01661                    fwSession->fwInstance) ) {
01662     CK_ULONG i;
01663 
01664     /*
01665      * Does the search criteria restrict us to token or session
01666      * objects?
01667      */
01668 
01669     for( i = 0; i < ulAttributeCount; i++ ) {
01670       if( CKA_TOKEN == pTemplate[i].type ) {
01671         /* Yes, it does. */
01672         CK_BBOOL isToken;
01673         if( sizeof(CK_BBOOL) != pTemplate[i].ulValueLen ) {
01674           *pError = CKR_ATTRIBUTE_VALUE_INVALID;
01675           return (NSSCKFWFindObjects *)NULL;
01676         }
01677         (void)nsslibc_memcpy(&isToken, pTemplate[i].pValue, sizeof(CK_BBOOL));
01678 
01679         if( CK_TRUE == isToken ) {
01680           /* Pass it on to the module's search routine */
01681           if( (void *)NULL == (void *)fwSession->mdSession->FindObjectsInit ) {
01682             goto wrap;
01683           }
01684 
01685           mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
01686                     fwSession, fwSession->mdToken, fwSession->fwToken,
01687                     fwSession->mdInstance, fwSession->fwInstance, 
01688                     pTemplate, ulAttributeCount, pError);
01689         } else {
01690           /* Do the search ourselves */
01691           mdfo1 = nssCKMDFindSessionObjects_Create(fwSession->fwToken, 
01692                     pTemplate, ulAttributeCount, pError);
01693         }
01694 
01695         if( (NSSCKMDFindObjects *)NULL == mdfo1 ) {
01696           if( CKR_OK == *pError ) {
01697             *pError = CKR_GENERAL_ERROR;
01698           }
01699           return (NSSCKFWFindObjects *)NULL;
01700         }
01701         
01702         goto wrap;
01703       }
01704     }
01705 
01706     if( i == ulAttributeCount ) {
01707       /* No, it doesn't.  Do a hybrid search. */
01708       mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
01709                 fwSession, fwSession->mdToken, fwSession->fwToken,
01710                 fwSession->mdInstance, fwSession->fwInstance, 
01711                 pTemplate, ulAttributeCount, pError);
01712 
01713       if( (NSSCKMDFindObjects *)NULL == mdfo1 ) {
01714         if( CKR_OK == *pError ) {
01715           *pError = CKR_GENERAL_ERROR;
01716         }
01717         return (NSSCKFWFindObjects *)NULL;
01718       }
01719 
01720       mdfo2 = nssCKMDFindSessionObjects_Create(fwSession->fwToken,
01721                 pTemplate, ulAttributeCount, pError);
01722       if( (NSSCKMDFindObjects *)NULL == mdfo2 ) {
01723         if( CKR_OK == *pError ) {
01724           *pError = CKR_GENERAL_ERROR;
01725         }
01726         if( (void *)NULL != (void *)mdfo1->Final ) {
01727           mdfo1->Final(mdfo1, (NSSCKFWFindObjects *)NULL, fwSession->mdSession,
01728             fwSession, fwSession->mdToken, fwSession->fwToken, 
01729             fwSession->mdInstance, fwSession->fwInstance);
01730         }
01731         return (NSSCKFWFindObjects *)NULL;
01732       }
01733 
01734       goto wrap;
01735     }
01736     /*NOTREACHED*/
01737   } else {
01738     /* Module handles all its own objects.  Pass on to module's search */
01739     mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
01740               fwSession, fwSession->mdToken, fwSession->fwToken,
01741               fwSession->mdInstance, fwSession->fwInstance, 
01742               pTemplate, ulAttributeCount, pError);
01743 
01744     if( (NSSCKMDFindObjects *)NULL == mdfo1 ) {
01745       if( CKR_OK == *pError ) {
01746         *pError = CKR_GENERAL_ERROR;
01747       }
01748       return (NSSCKFWFindObjects *)NULL;
01749     }
01750 
01751     goto wrap;
01752   }
01753 
01754  wrap:
01755   return nssCKFWFindObjects_Create(fwSession, fwSession->fwToken,
01756            fwSession->fwInstance, mdfo1, mdfo2, pError);
01757 }
01758 
01759 /*
01760  * nssCKFWSession_SeedRandom
01761  *
01762  */
01763 NSS_IMPLEMENT CK_RV
01764 nssCKFWSession_SeedRandom
01765 (
01766   NSSCKFWSession *fwSession,
01767   NSSItem *seed
01768 )
01769 {
01770   CK_RV error = CKR_OK;
01771 
01772 #ifdef NSSDEBUG
01773   error = nssCKFWSession_verifyPointer(fwSession);
01774   if( CKR_OK != error ) {
01775     return error;
01776   }
01777 
01778   if( (NSSItem *)NULL == seed ) {
01779     return CKR_ARGUMENTS_BAD;
01780   }
01781 
01782   if( (void *)NULL == seed->data ) {
01783     return CKR_ARGUMENTS_BAD;
01784   }
01785 
01786   if( 0 == seed->size ) {
01787     return CKR_ARGUMENTS_BAD;
01788   }
01789 
01790   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
01791     return CKR_GENERAL_ERROR;
01792   }
01793 #endif /* NSSDEBUG */
01794 
01795   if( (void *)NULL == (void *)fwSession->mdSession->SeedRandom ) {
01796     return CKR_RANDOM_SEED_NOT_SUPPORTED;
01797   }
01798 
01799   error = fwSession->mdSession->SeedRandom(fwSession->mdSession, fwSession,
01800     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
01801     fwSession->fwInstance, seed);
01802 
01803   return error;
01804 }
01805 
01806 /*
01807  * nssCKFWSession_GetRandom
01808  *
01809  */
01810 NSS_IMPLEMENT CK_RV
01811 nssCKFWSession_GetRandom
01812 (
01813   NSSCKFWSession *fwSession,
01814   NSSItem *buffer
01815 )
01816 {
01817   CK_RV error = CKR_OK;
01818 
01819 #ifdef NSSDEBUG
01820   error = nssCKFWSession_verifyPointer(fwSession);
01821   if( CKR_OK != error ) {
01822     return error;
01823   }
01824 
01825   if( (NSSItem *)NULL == buffer ) {
01826     return CKR_ARGUMENTS_BAD;
01827   }
01828 
01829   if( (void *)NULL == buffer->data ) {
01830     return CKR_ARGUMENTS_BAD;
01831   }
01832 
01833   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
01834     return CKR_GENERAL_ERROR;
01835   }
01836 #endif /* NSSDEBUG */
01837 
01838   if( (void *)NULL == (void *)fwSession->mdSession->GetRandom ) {
01839     if( CK_TRUE == nssCKFWToken_GetHasRNG(fwSession->fwToken) ) {
01840       return CKR_GENERAL_ERROR;
01841     } else {
01842       return CKR_RANDOM_NO_RNG;
01843     }
01844   }
01845 
01846   if( 0 == buffer->size ) {
01847     return CKR_OK;
01848   }
01849 
01850   error = fwSession->mdSession->GetRandom(fwSession->mdSession, fwSession,
01851     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
01852     fwSession->fwInstance, buffer);
01853 
01854   return error;
01855 }
01856 
01857 /*
01858  * NSSCKFWSession_GetMDSession
01859  *
01860  */
01861 
01862 NSS_IMPLEMENT NSSCKMDSession *
01863 NSSCKFWSession_GetMDSession
01864 (
01865   NSSCKFWSession *fwSession
01866 )
01867 {
01868 #ifdef DEBUG
01869   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
01870     return (NSSCKMDSession *)NULL;
01871   }
01872 #endif /* DEBUG */
01873 
01874   return nssCKFWSession_GetMDSession(fwSession);
01875 }
01876 
01877 /*
01878  * NSSCKFWSession_GetArena
01879  *
01880  */
01881 
01882 NSS_IMPLEMENT NSSArena *
01883 NSSCKFWSession_GetArena
01884 (
01885   NSSCKFWSession *fwSession,
01886   CK_RV *pError
01887 )
01888 {
01889 #ifdef DEBUG
01890   if( (CK_RV *)NULL == pError ) {
01891     return (NSSArena *)NULL;
01892   }
01893 
01894   *pError = nssCKFWSession_verifyPointer(fwSession);
01895   if( CKR_OK != *pError ) {
01896     return (NSSArena *)NULL;
01897   }
01898 #endif /* DEBUG */
01899 
01900   return nssCKFWSession_GetArena(fwSession, pError);
01901 }
01902 
01903 /*
01904  * NSSCKFWSession_CallNotification
01905  *
01906  */
01907 
01908 NSS_IMPLEMENT CK_RV
01909 NSSCKFWSession_CallNotification
01910 (
01911   NSSCKFWSession *fwSession,
01912   CK_NOTIFICATION event
01913 )
01914 {
01915 #ifdef DEBUG
01916   CK_RV error = CKR_OK;
01917 
01918   error = nssCKFWSession_verifyPointer(fwSession);
01919   if( CKR_OK != error ) {
01920     return error;
01921   }
01922 #endif /* DEBUG */
01923 
01924   return nssCKFWSession_CallNotification(fwSession, event);
01925 }
01926 
01927 /*
01928  * NSSCKFWSession_IsRWSession
01929  *
01930  */
01931 
01932 NSS_IMPLEMENT CK_BBOOL
01933 NSSCKFWSession_IsRWSession
01934 (
01935   NSSCKFWSession *fwSession
01936 )
01937 {
01938 #ifdef DEBUG
01939   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
01940     return CK_FALSE;
01941   }
01942 #endif /* DEBUG */
01943 
01944   return nssCKFWSession_IsRWSession(fwSession);
01945 }
01946 
01947 /*
01948  * NSSCKFWSession_IsSO
01949  *
01950  */
01951 
01952 NSS_IMPLEMENT CK_BBOOL
01953 NSSCKFWSession_IsSO
01954 (
01955   NSSCKFWSession *fwSession
01956 )
01957 {
01958 #ifdef DEBUG
01959   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
01960     return CK_FALSE;
01961   }
01962 #endif /* DEBUG */
01963 
01964   return nssCKFWSession_IsSO(fwSession);
01965 }