security/nss/lib/ckfw/session.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     5 /*
     6  * session.c
     7  *
     8  * This file implements the NSSCKFWSession type and methods.
     9  */
    11 #ifndef CK_T
    12 #include "ck.h"
    13 #endif /* CK_T */
    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  *
    29  *  -- implement public accessors --
    30  *  nssCKFWSession_GetMDSession
    31  *  nssCKFWSession_GetArena
    32  *  nssCKFWSession_CallNotification
    33  *  nssCKFWSession_IsRWSession
    34  *  nssCKFWSession_IsSO
    35  *
    36  *  -- private accessors --
    37  *  nssCKFWSession_GetSlot
    38  *  nssCKFWSession_GetSessionState
    39  *  nssCKFWSession_SetFWFindObjects
    40  *  nssCKFWSession_GetFWFindObjects
    41  *  nssCKFWSession_SetMDSession
    42  *  nssCKFWSession_SetHandle
    43  *  nssCKFWSession_GetHandle
    44  *  nssCKFWSession_RegisterSessionObject
    45  *  nssCKFWSession_DeegisterSessionObject
    46  *
    47  *  -- module fronts --
    48  *  nssCKFWSession_GetDeviceError
    49  *  nssCKFWSession_Login
    50  *  nssCKFWSession_Logout
    51  *  nssCKFWSession_InitPIN
    52  *  nssCKFWSession_SetPIN
    53  *  nssCKFWSession_GetOperationStateLen
    54  *  nssCKFWSession_GetOperationState
    55  *  nssCKFWSession_SetOperationState
    56  *  nssCKFWSession_CreateObject
    57  *  nssCKFWSession_CopyObject
    58  *  nssCKFWSession_FindObjectsInit
    59  *  nssCKFWSession_SeedRandom
    60  *  nssCKFWSession_GetRandom
    61  */
    63 struct NSSCKFWSessionStr {
    64   NSSArena *arena;
    65   NSSCKMDSession *mdSession;
    66   NSSCKFWToken *fwToken;
    67   NSSCKMDToken *mdToken;
    68   NSSCKFWInstance *fwInstance;
    69   NSSCKMDInstance *mdInstance;
    70   CK_VOID_PTR pApplication;
    71   CK_NOTIFY Notify;
    73   /*
    74    * Everything above is set at creation time, and then not modified.
    75    * The items below are atomic.  No locking required.  If we fear
    76    * about pointer-copies being nonatomic, we'll lock fwFindObjects.
    77    */
    79   CK_BBOOL rw;
    80   NSSCKFWFindObjects *fwFindObjects;
    81   NSSCKFWCryptoOperation *fwOperationArray[NSSCKFWCryptoOperationState_Max];
    82   nssCKFWHash *sessionObjectHash;
    83   CK_SESSION_HANDLE hSession;
    84 };
    86 #ifdef DEBUG
    87 /*
    88  * But first, the pointer-tracking stuff.
    89  *
    90  * NOTE: the pointer-tracking support in NSS/base currently relies
    91  * upon NSPR's CallOnce support.  That, however, relies upon NSPR's
    92  * locking, which is tied into the runtime.  We need a pointer-tracker
    93  * implementation that uses the locks supplied through C_Initialize.
    94  * That support, however, can be filled in later.  So for now, I'll
    95  * just do this routines as no-ops.
    96  */
    98 static CK_RV
    99 session_add_pointer
   100 (
   101   const NSSCKFWSession *fwSession
   102 )
   103 {
   104   return CKR_OK;
   105 }
   107 static CK_RV
   108 session_remove_pointer
   109 (
   110   const NSSCKFWSession *fwSession
   111 )
   112 {
   113   return CKR_OK;
   114 }
   116 NSS_IMPLEMENT CK_RV
   117 nssCKFWSession_verifyPointer
   118 (
   119   const NSSCKFWSession *fwSession
   120 )
   121 {
   122   return CKR_OK;
   123 }
   125 #endif /* DEBUG */
   127 /*
   128  * nssCKFWSession_Create
   129  *
   130  */
   131 NSS_IMPLEMENT NSSCKFWSession *
   132 nssCKFWSession_Create
   133 (
   134   NSSCKFWToken *fwToken,
   135   CK_BBOOL rw,
   136   CK_VOID_PTR pApplication,
   137   CK_NOTIFY Notify,
   138   CK_RV *pError
   139 )
   140 {
   141   NSSArena *arena = (NSSArena *)NULL;
   142   NSSCKFWSession *fwSession;
   143   NSSCKFWSlot *fwSlot;
   145 #ifdef NSSDEBUG
   146   if (!pError) {
   147     return (NSSCKFWSession *)NULL;
   148   }
   150   *pError = nssCKFWToken_verifyPointer(fwToken);
   151   if( CKR_OK != *pError ) {
   152     return (NSSCKFWSession *)NULL;
   153   }
   154 #endif /* NSSDEBUG */
   156   arena = NSSArena_Create();
   157   if (!arena) {
   158     *pError = CKR_HOST_MEMORY;
   159     return (NSSCKFWSession *)NULL;
   160   }
   162   fwSession = nss_ZNEW(arena, NSSCKFWSession);
   163   if (!fwSession) {
   164     *pError = CKR_HOST_MEMORY;
   165     goto loser;
   166   }
   168   fwSession->arena = arena;
   169   fwSession->mdSession = (NSSCKMDSession *)NULL; /* set later */
   170   fwSession->fwToken = fwToken;
   171   fwSession->mdToken = nssCKFWToken_GetMDToken(fwToken);
   173   fwSlot = nssCKFWToken_GetFWSlot(fwToken);
   174   fwSession->fwInstance = nssCKFWSlot_GetFWInstance(fwSlot);
   175   fwSession->mdInstance = nssCKFWSlot_GetMDInstance(fwSlot);
   177   fwSession->rw = rw;
   178   fwSession->pApplication = pApplication;
   179   fwSession->Notify = Notify;
   181   fwSession->fwFindObjects = (NSSCKFWFindObjects *)NULL;
   183   fwSession->sessionObjectHash = nssCKFWHash_Create(fwSession->fwInstance, arena, pError);
   184   if (!fwSession->sessionObjectHash) {
   185     if( CKR_OK == *pError ) {
   186       *pError = CKR_GENERAL_ERROR;
   187     }
   188     goto loser;
   189   }
   191 #ifdef DEBUG
   192   *pError = session_add_pointer(fwSession);
   193   if( CKR_OK != *pError ) {
   194     goto loser;
   195   }
   196 #endif /* DEBUG */
   198   return fwSession;
   200  loser:
   201   if (arena) {
   202     if (fwSession &&   fwSession->sessionObjectHash) {
   203       (void)nssCKFWHash_Destroy(fwSession->sessionObjectHash);
   204     }
   205     NSSArena_Destroy(arena);
   206   }
   208   return (NSSCKFWSession *)NULL;
   209 }
   211 static void
   212 nss_ckfw_session_object_destroy_iterator
   213 (
   214   const void *key,
   215   void *value,
   216   void *closure
   217 )
   218 {
   219   NSSCKFWObject *fwObject = (NSSCKFWObject *)value;
   220   nssCKFWObject_Finalize(fwObject, PR_TRUE);
   221 }
   223 /*
   224  * nssCKFWSession_Destroy
   225  *
   226  */
   227 NSS_IMPLEMENT CK_RV
   228 nssCKFWSession_Destroy
   229 (
   230   NSSCKFWSession *fwSession,
   231   CK_BBOOL removeFromTokenHash
   232 )
   233 {
   234   CK_RV error = CKR_OK;
   235   nssCKFWHash *sessionObjectHash;
   236   NSSCKFWCryptoOperationState i;
   238 #ifdef NSSDEBUG
   239   error = nssCKFWSession_verifyPointer(fwSession);
   240   if( CKR_OK != error ) {
   241     return error;
   242   }
   243 #endif /* NSSDEBUG */
   245   if( removeFromTokenHash ) {
   246     error = nssCKFWToken_RemoveSession(fwSession->fwToken, fwSession);
   247   }
   249   /*
   250    * Invalidate session objects
   251    */
   253   sessionObjectHash = fwSession->sessionObjectHash;
   254   fwSession->sessionObjectHash = (nssCKFWHash *)NULL;
   256   nssCKFWHash_Iterate(sessionObjectHash, 
   257                       nss_ckfw_session_object_destroy_iterator, 
   258                       (void *)NULL);
   260   for (i=0; i < NSSCKFWCryptoOperationState_Max; i++) {
   261     if (fwSession->fwOperationArray[i]) {
   262       nssCKFWCryptoOperation_Destroy(fwSession->fwOperationArray[i]);
   263     }
   264   }
   266 #ifdef DEBUG
   267   (void)session_remove_pointer(fwSession);
   268 #endif /* DEBUG */
   269   (void)nssCKFWHash_Destroy(sessionObjectHash);
   270   NSSArena_Destroy(fwSession->arena);
   272   return error;
   273 }
   275 /*
   276  * nssCKFWSession_GetMDSession
   277  *
   278  */
   279 NSS_IMPLEMENT NSSCKMDSession *
   280 nssCKFWSession_GetMDSession
   281 (
   282   NSSCKFWSession *fwSession
   283 )
   284 {
   285 #ifdef NSSDEBUG
   286   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   287     return (NSSCKMDSession *)NULL;
   288   }
   289 #endif /* NSSDEBUG */
   291   return fwSession->mdSession;
   292 }
   294 /*
   295  * nssCKFWSession_GetArena
   296  *
   297  */
   298 NSS_IMPLEMENT NSSArena *
   299 nssCKFWSession_GetArena
   300 (
   301   NSSCKFWSession *fwSession,
   302   CK_RV *pError
   303 )
   304 {
   305 #ifdef NSSDEBUG
   306   if (!pError) {
   307     return (NSSArena *)NULL;
   308   }
   310   *pError = nssCKFWSession_verifyPointer(fwSession);
   311   if( CKR_OK != *pError ) {
   312     return (NSSArena *)NULL;
   313   }
   314 #endif /* NSSDEBUG */
   316   return fwSession->arena;
   317 }
   319 /*
   320  * nssCKFWSession_CallNotification
   321  *
   322  */
   323 NSS_IMPLEMENT CK_RV
   324 nssCKFWSession_CallNotification
   325 (
   326   NSSCKFWSession *fwSession,
   327   CK_NOTIFICATION event
   328 )
   329 {
   330   CK_RV error = CKR_OK;
   331   CK_SESSION_HANDLE handle;
   333 #ifdef NSSDEBUG
   334   error = nssCKFWSession_verifyPointer(fwSession);
   335   if( CKR_OK != error ) {
   336     return error;
   337   }
   338 #endif /* NSSDEBUG */
   340   if( (CK_NOTIFY)NULL == fwSession->Notify ) {
   341     return CKR_OK;
   342   }
   344   handle = nssCKFWInstance_FindSessionHandle(fwSession->fwInstance, fwSession);
   345   if( (CK_SESSION_HANDLE)0 == handle ) {
   346     return CKR_GENERAL_ERROR;
   347   }
   349   error = fwSession->Notify(handle, event, fwSession->pApplication);
   351   return error;
   352 }
   354 /*
   355  * nssCKFWSession_IsRWSession
   356  *
   357  */
   358 NSS_IMPLEMENT CK_BBOOL
   359 nssCKFWSession_IsRWSession
   360 (
   361   NSSCKFWSession *fwSession
   362 )
   363 {
   364 #ifdef NSSDEBUG
   365   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   366     return CK_FALSE;
   367   }
   368 #endif /* NSSDEBUG */
   370   return fwSession->rw;
   371 }
   373 /*
   374  * nssCKFWSession_IsSO
   375  *
   376  */
   377 NSS_IMPLEMENT CK_BBOOL
   378 nssCKFWSession_IsSO
   379 (
   380   NSSCKFWSession *fwSession
   381 )
   382 {
   383   CK_STATE state;
   385 #ifdef NSSDEBUG
   386   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   387     return CK_FALSE;
   388   }
   389 #endif /* NSSDEBUG */
   391   state = nssCKFWToken_GetSessionState(fwSession->fwToken);
   392   switch( state ) {
   393   case CKS_RO_PUBLIC_SESSION:
   394   case CKS_RO_USER_FUNCTIONS:
   395   case CKS_RW_PUBLIC_SESSION:
   396   case CKS_RW_USER_FUNCTIONS:
   397     return CK_FALSE;
   398   case CKS_RW_SO_FUNCTIONS:
   399     return CK_TRUE;
   400   default:
   401     return CK_FALSE;
   402   }
   403 }
   405 /*
   406  * nssCKFWSession_GetFWSlot
   407  *
   408  */
   409 NSS_IMPLEMENT NSSCKFWSlot *
   410 nssCKFWSession_GetFWSlot
   411 (
   412   NSSCKFWSession *fwSession
   413 )
   414 {
   415 #ifdef NSSDEBUG
   416   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   417     return (NSSCKFWSlot *)NULL;
   418   }
   419 #endif /* NSSDEBUG */
   421   return nssCKFWToken_GetFWSlot(fwSession->fwToken);
   422 }
   424 /*
   425  * nssCFKWSession_GetSessionState
   426  *
   427  */
   428 NSS_IMPLEMENT CK_STATE
   429 nssCKFWSession_GetSessionState
   430 (
   431   NSSCKFWSession *fwSession
   432 )
   433 {
   434 #ifdef NSSDEBUG
   435   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   436     return CKS_RO_PUBLIC_SESSION; /* whatever */
   437   }
   438 #endif /* NSSDEBUG */
   440   return nssCKFWToken_GetSessionState(fwSession->fwToken);
   441 }
   443 /*
   444  * nssCKFWSession_SetFWFindObjects
   445  *
   446  */
   447 NSS_IMPLEMENT CK_RV
   448 nssCKFWSession_SetFWFindObjects
   449 (
   450   NSSCKFWSession *fwSession,
   451   NSSCKFWFindObjects *fwFindObjects
   452 )
   453 {
   454 #ifdef NSSDEBUG
   455   CK_RV error = CKR_OK;
   456 #endif /* NSSDEBUG */
   458 #ifdef NSSDEBUG
   459   error = nssCKFWSession_verifyPointer(fwSession);
   460   if( CKR_OK != error ) {
   461     return error;
   462   }
   464   /* fwFindObjects may be null */
   465 #endif /* NSSDEBUG */
   467   if ((fwSession->fwFindObjects) &&
   468       (fwFindObjects)) {
   469     return CKR_OPERATION_ACTIVE;
   470   }
   472   fwSession->fwFindObjects = fwFindObjects;
   474   return CKR_OK;
   475 }
   477 /*
   478  * nssCKFWSession_GetFWFindObjects
   479  *
   480  */
   481 NSS_IMPLEMENT NSSCKFWFindObjects *
   482 nssCKFWSession_GetFWFindObjects
   483 (
   484   NSSCKFWSession *fwSession,
   485   CK_RV *pError
   486 )
   487 {
   488 #ifdef NSSDEBUG
   489   if (!pError) {
   490     return (NSSCKFWFindObjects *)NULL;
   491   }
   493   *pError = nssCKFWSession_verifyPointer(fwSession);
   494   if( CKR_OK != *pError ) {
   495     return (NSSCKFWFindObjects *)NULL;
   496   }
   497 #endif /* NSSDEBUG */
   499   if (!fwSession->fwFindObjects) {
   500     *pError = CKR_OPERATION_NOT_INITIALIZED;
   501     return (NSSCKFWFindObjects *)NULL;
   502   }
   504   return fwSession->fwFindObjects;
   505 }
   507 /*
   508  * nssCKFWSession_SetMDSession
   509  *
   510  */
   511 NSS_IMPLEMENT CK_RV
   512 nssCKFWSession_SetMDSession
   513 (
   514   NSSCKFWSession *fwSession,
   515   NSSCKMDSession *mdSession
   516 )
   517 {
   518 #ifdef NSSDEBUG
   519   CK_RV error = CKR_OK;
   520 #endif /* NSSDEBUG */
   522 #ifdef NSSDEBUG
   523   error = nssCKFWSession_verifyPointer(fwSession);
   524   if( CKR_OK != error ) {
   525     return error;
   526   }
   528   if (!mdSession) {
   529     return CKR_ARGUMENTS_BAD;
   530   }
   531 #endif /* NSSDEBUG */
   533   if (fwSession->mdSession) {
   534     return CKR_GENERAL_ERROR;
   535   }
   537   fwSession->mdSession = mdSession;
   539   return CKR_OK;
   540 }
   542 /*
   543  * nssCKFWSession_SetHandle
   544  *
   545  */
   546 NSS_IMPLEMENT CK_RV
   547 nssCKFWSession_SetHandle
   548 (
   549   NSSCKFWSession *fwSession,
   550   CK_SESSION_HANDLE hSession
   551 )
   552 {
   553 #ifdef NSSDEBUG
   554   CK_RV error = CKR_OK;
   555 #endif /* NSSDEBUG */
   557 #ifdef NSSDEBUG
   558   error = nssCKFWSession_verifyPointer(fwSession);
   559   if( CKR_OK != error ) {
   560     return error;
   561   }
   562 #endif /* NSSDEBUG */
   564   if( (CK_SESSION_HANDLE)0 != fwSession->hSession ) {
   565     return CKR_GENERAL_ERROR;
   566   }
   568   fwSession->hSession = hSession;
   570   return CKR_OK;
   571 }
   573 /*
   574  * nssCKFWSession_GetHandle
   575  *
   576  */
   577 NSS_IMPLEMENT CK_SESSION_HANDLE
   578 nssCKFWSession_GetHandle
   579 (
   580   NSSCKFWSession *fwSession
   581 )
   582 {
   583 #ifdef NSSDEBUG
   584   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   585     return NULL;
   586   }
   587 #endif /* NSSDEBUG */
   589   return fwSession->hSession;
   590 }
   592 /*
   593  * nssCKFWSession_RegisterSessionObject
   594  *
   595  */
   596 NSS_IMPLEMENT CK_RV
   597 nssCKFWSession_RegisterSessionObject
   598 (
   599   NSSCKFWSession *fwSession,
   600   NSSCKFWObject *fwObject
   601 )
   602 {
   603   CK_RV rv = CKR_OK;
   605 #ifdef NSSDEBUG
   606   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   607     return CKR_GENERAL_ERROR;
   608   }
   609 #endif /* NSSDEBUG */
   611   if (fwSession->sessionObjectHash) {
   612     rv = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject);
   613   }
   615   return rv;
   616 }
   618 /*
   619  * nssCKFWSession_DeregisterSessionObject
   620  *
   621  */
   622 NSS_IMPLEMENT CK_RV
   623 nssCKFWSession_DeregisterSessionObject
   624 (
   625   NSSCKFWSession *fwSession,
   626   NSSCKFWObject *fwObject
   627 )
   628 {
   629 #ifdef NSSDEBUG
   630   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   631     return CKR_GENERAL_ERROR;
   632   }
   633 #endif /* NSSDEBUG */
   635   if (fwSession->sessionObjectHash) {
   636     nssCKFWHash_Remove(fwSession->sessionObjectHash, fwObject);
   637   }
   639   return CKR_OK;
   640 }
   642 /*
   643  * nssCKFWSession_GetDeviceError
   644  *
   645  */
   646 NSS_IMPLEMENT CK_ULONG
   647 nssCKFWSession_GetDeviceError
   648 (
   649   NSSCKFWSession *fwSession
   650 )
   651 {
   652 #ifdef NSSDEBUG
   653   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   654     return (CK_ULONG)0;
   655   }
   657   if (!fwSession->mdSession) {
   658     return (CK_ULONG)0;
   659   }
   660 #endif /* NSSDEBUG */
   662   if (!fwSession->mdSession->GetDeviceError) {
   663     return (CK_ULONG)0;
   664   }
   666   return fwSession->mdSession->GetDeviceError(fwSession->mdSession, 
   667     fwSession, fwSession->mdToken, fwSession->fwToken, 
   668     fwSession->mdInstance, fwSession->fwInstance);
   669 }
   671 /*
   672  * nssCKFWSession_Login
   673  *
   674  */
   675 NSS_IMPLEMENT CK_RV
   676 nssCKFWSession_Login
   677 (
   678   NSSCKFWSession *fwSession,
   679   CK_USER_TYPE userType,
   680   NSSItem *pin
   681 )
   682 {
   683   CK_RV error = CKR_OK;
   684   CK_STATE oldState;
   685   CK_STATE newState;
   687 #ifdef NSSDEBUG
   688   error = nssCKFWSession_verifyPointer(fwSession);
   689   if( CKR_OK != error ) {
   690     return error;
   691   }
   693   switch( userType ) {
   694   case CKU_SO:
   695   case CKU_USER:
   696     break;
   697   default:
   698     return CKR_USER_TYPE_INVALID;
   699   }
   701   if (!pin) {
   702     if( CK_TRUE != nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken) ) {
   703       return CKR_ARGUMENTS_BAD;
   704     }
   705   }
   707   if (!fwSession->mdSession) {
   708     return CKR_GENERAL_ERROR;
   709   }
   710 #endif /* NSSDEBUG */
   712   oldState = nssCKFWToken_GetSessionState(fwSession->fwToken);
   714   /*
   715    * It's not clear what happens when you're already logged in.
   716    * I'll just fail; but if we decide to change, the logic is
   717    * all right here.
   718    */
   720   if( CKU_SO == userType ) {
   721     switch( oldState ) {
   722     case CKS_RO_PUBLIC_SESSION:      
   723       /*
   724        * There's no such thing as a read-only security officer
   725        * session, so fail.  The error should be CKR_SESSION_READ_ONLY,
   726        * except that C_Login isn't defined to return that.  So we'll
   727        * do CKR_SESSION_READ_ONLY_EXISTS, which is what is documented.
   728        */
   729       return CKR_SESSION_READ_ONLY_EXISTS;
   730     case CKS_RO_USER_FUNCTIONS:
   731       return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
   732     case CKS_RW_PUBLIC_SESSION:
   733       newState = CKS_RW_SO_FUNCTIONS;
   734       break;
   735     case CKS_RW_USER_FUNCTIONS:
   736       return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
   737     case CKS_RW_SO_FUNCTIONS:
   738       return CKR_USER_ALREADY_LOGGED_IN;
   739     default:
   740       return CKR_GENERAL_ERROR;
   741     }
   742   } else /* CKU_USER == userType */ {
   743     switch( oldState ) {
   744     case CKS_RO_PUBLIC_SESSION:      
   745       newState = CKS_RO_USER_FUNCTIONS;
   746       break;
   747     case CKS_RO_USER_FUNCTIONS:
   748       return CKR_USER_ALREADY_LOGGED_IN;
   749     case CKS_RW_PUBLIC_SESSION:
   750       newState = CKS_RW_USER_FUNCTIONS;
   751       break;
   752     case CKS_RW_USER_FUNCTIONS:
   753       return CKR_USER_ALREADY_LOGGED_IN;
   754     case CKS_RW_SO_FUNCTIONS:
   755       return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
   756     default:
   757       return CKR_GENERAL_ERROR;
   758     }
   759   }
   761   /*
   762    * So now we're in one of three cases:
   763    *
   764    * Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_SO_FUNCTIONS;
   765    * Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_USER_FUNCTIONS;
   766    * Old == CKS_RO_PUBLIC_SESSION, New == CKS_RO_USER_FUNCTIONS;
   767    */
   769   if (!fwSession->mdSession->Login) {
   770     /*
   771      * The Module doesn't want to be informed (or check the pin)
   772      * it'll just rely on the Framework as needed.
   773      */
   774     ;
   775   } else {
   776     error = fwSession->mdSession->Login(fwSession->mdSession, fwSession,
   777       fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
   778       fwSession->fwInstance, userType, pin, oldState, newState);
   779     if( CKR_OK != error ) {
   780       return error;
   781     }
   782   }
   784   (void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState);
   785   return CKR_OK;
   786 }
   788 /*
   789  * nssCKFWSession_Logout
   790  *
   791  */
   792 NSS_IMPLEMENT CK_RV
   793 nssCKFWSession_Logout
   794 (
   795   NSSCKFWSession *fwSession
   796 )
   797 {
   798   CK_RV error = CKR_OK;
   799   CK_STATE oldState;
   800   CK_STATE newState;
   802 #ifdef NSSDEBUG
   803   error = nssCKFWSession_verifyPointer(fwSession);
   804   if( CKR_OK != error ) {
   805     return error;
   806   }
   808   if (!fwSession->mdSession) {
   809     return CKR_GENERAL_ERROR;
   810   }
   811 #endif /* NSSDEBUG */
   813   oldState = nssCKFWToken_GetSessionState(fwSession->fwToken);
   815   switch( oldState ) {
   816   case CKS_RO_PUBLIC_SESSION:
   817     return CKR_USER_NOT_LOGGED_IN;
   818   case CKS_RO_USER_FUNCTIONS:
   819     newState = CKS_RO_PUBLIC_SESSION;
   820     break;
   821   case CKS_RW_PUBLIC_SESSION:
   822     return CKR_USER_NOT_LOGGED_IN;
   823   case CKS_RW_USER_FUNCTIONS:
   824     newState = CKS_RW_PUBLIC_SESSION;
   825     break;
   826   case CKS_RW_SO_FUNCTIONS:
   827     newState = CKS_RW_PUBLIC_SESSION;
   828     break;
   829   default:
   830     return CKR_GENERAL_ERROR;
   831   }
   833   /*
   834    * So now we're in one of three cases:
   835    *
   836    * Old == CKS_RW_SO_FUNCTIONS,   New == CKS_RW_PUBLIC_SESSION;
   837    * Old == CKS_RW_USER_FUNCTIONS, New == CKS_RW_PUBLIC_SESSION;
   838    * Old == CKS_RO_USER_FUNCTIONS, New == CKS_RO_PUBLIC_SESSION;
   839    */
   841   if (!fwSession->mdSession->Logout) {
   842     /*
   843      * The Module doesn't want to be informed.  Okay.
   844      */
   845     ;
   846   } else {
   847     error = fwSession->mdSession->Logout(fwSession->mdSession, fwSession,
   848       fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
   849       fwSession->fwInstance, oldState, newState);
   850     if( CKR_OK != error ) {
   851       /*
   852        * Now what?!  A failure really should end up with the Framework
   853        * considering it logged out, right?
   854        */
   855       ;
   856     }
   857   }
   859   (void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState);
   860   return error;
   861 }
   863 /*
   864  * nssCKFWSession_InitPIN
   865  *
   866  */
   867 NSS_IMPLEMENT CK_RV
   868 nssCKFWSession_InitPIN
   869 (
   870   NSSCKFWSession *fwSession,
   871   NSSItem *pin
   872 )
   873 {
   874   CK_RV error = CKR_OK;
   875   CK_STATE state;
   877 #ifdef NSSDEBUG
   878   error = nssCKFWSession_verifyPointer(fwSession);
   879   if( CKR_OK != error ) {
   880     return error;
   881   }
   883   if (!fwSession->mdSession) {
   884     return CKR_GENERAL_ERROR;
   885   }
   886 #endif /* NSSDEBUG */
   888   state = nssCKFWToken_GetSessionState(fwSession->fwToken);
   889   if( CKS_RW_SO_FUNCTIONS != state ) {
   890     return CKR_USER_NOT_LOGGED_IN;
   891   }
   893   if (!pin) {
   894     CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
   895     if( CK_TRUE != has ) {
   896       return CKR_ARGUMENTS_BAD;
   897     }
   898   }
   900   if (!fwSession->mdSession->InitPIN) {
   901     return CKR_TOKEN_WRITE_PROTECTED;
   902   }
   904   error = fwSession->mdSession->InitPIN(fwSession->mdSession, fwSession,
   905     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
   906     fwSession->fwInstance, pin);
   908   return error;
   909 }
   911 /*
   912  * nssCKFWSession_SetPIN
   913  *
   914  */
   915 NSS_IMPLEMENT CK_RV
   916 nssCKFWSession_SetPIN
   917 (
   918   NSSCKFWSession *fwSession,
   919   NSSItem *newPin,
   920   NSSItem *oldPin
   921 )
   922 {
   923   CK_RV error = CKR_OK;
   925 #ifdef NSSDEBUG
   926   error = nssCKFWSession_verifyPointer(fwSession);
   927   if( CKR_OK != error ) {
   928     return error;
   929   }
   931   if (!fwSession->mdSession) {
   932     return CKR_GENERAL_ERROR;
   933   }
   934 #endif /* NSSDEBUG */
   936   if (!newPin) {
   937     CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
   938     if( CK_TRUE != has ) {
   939       return CKR_ARGUMENTS_BAD;
   940     }
   941   }
   943   if (!oldPin) {
   944     CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
   945     if( CK_TRUE != has ) {
   946       return CKR_ARGUMENTS_BAD;
   947     }
   948   }
   950   if (!fwSession->mdSession->SetPIN) {
   951     return CKR_TOKEN_WRITE_PROTECTED;
   952   }
   954   error = fwSession->mdSession->SetPIN(fwSession->mdSession, fwSession,
   955     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
   956     fwSession->fwInstance, newPin, oldPin);
   958   return error;
   959 }
   961 /*
   962  * nssCKFWSession_GetOperationStateLen
   963  *
   964  */
   965 NSS_IMPLEMENT CK_ULONG
   966 nssCKFWSession_GetOperationStateLen
   967 (
   968   NSSCKFWSession *fwSession,
   969   CK_RV *pError
   970 )
   971 {
   972   CK_ULONG mdAmt;
   973   CK_ULONG fwAmt;
   975 #ifdef NSSDEBUG
   976   if (!pError) {
   977     return (CK_ULONG)0;
   978   }
   980   *pError = nssCKFWSession_verifyPointer(fwSession);
   981   if( CKR_OK != *pError ) {
   982     return (CK_ULONG)0;
   983   }
   985   if (!fwSession->mdSession) {
   986     *pError = CKR_GENERAL_ERROR;
   987     return (CK_ULONG)0;
   988   }
   989 #endif /* NSSDEBUG */
   991   if (!fwSession->mdSession->GetOperationStateLen) {
   992     *pError = CKR_STATE_UNSAVEABLE;
   993     return (CK_ULONG)0;
   994   }
   996   /*
   997    * We could check that the session is actually in some state..
   998    */
  1000   mdAmt = fwSession->mdSession->GetOperationStateLen(fwSession->mdSession,
  1001     fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  1002     fwSession->fwInstance, pError);
  1004   if( ((CK_ULONG)0 == mdAmt) && (CKR_OK != *pError) ) {
  1005     return (CK_ULONG)0;
  1008   /*
  1009    * Add a bit of sanity-checking
  1010    */
  1011   fwAmt = mdAmt + 2*sizeof(CK_ULONG);
  1013   return fwAmt;
  1016 /*
  1017  * nssCKFWSession_GetOperationState
  1019  */
  1020 NSS_IMPLEMENT CK_RV
  1021 nssCKFWSession_GetOperationState
  1023   NSSCKFWSession *fwSession,
  1024   NSSItem *buffer
  1027   CK_RV error = CKR_OK;
  1028   CK_ULONG fwAmt;
  1029   CK_ULONG *ulBuffer;
  1030   NSSItem i2;
  1031   CK_ULONG n, i;
  1033 #ifdef NSSDEBUG
  1034   error = nssCKFWSession_verifyPointer(fwSession);
  1035   if( CKR_OK != error ) {
  1036     return error;
  1039   if (!buffer) {
  1040     return CKR_ARGUMENTS_BAD;
  1043   if (!buffer->data) {
  1044     return CKR_ARGUMENTS_BAD;
  1047   if (!fwSession->mdSession) {
  1048     return CKR_GENERAL_ERROR;
  1050 #endif /* NSSDEBUG */
  1052   if (!fwSession->mdSession->GetOperationState) {
  1053     return CKR_STATE_UNSAVEABLE;
  1056   /*
  1057    * Sanity-check the caller's buffer.
  1058    */
  1060   error = CKR_OK;
  1061   fwAmt = nssCKFWSession_GetOperationStateLen(fwSession, &error);
  1062   if( ((CK_ULONG)0 == fwAmt) && (CKR_OK != error) ) {
  1063     return error;
  1066   if( buffer->size < fwAmt ) {
  1067     return CKR_BUFFER_TOO_SMALL;
  1070   ulBuffer = (CK_ULONG *)buffer->data;
  1072   i2.size = buffer->size - 2*sizeof(CK_ULONG);
  1073   i2.data = (void *)&ulBuffer[2];
  1075   error = fwSession->mdSession->GetOperationState(fwSession->mdSession,
  1076     fwSession, fwSession->mdToken, fwSession->fwToken, 
  1077     fwSession->mdInstance, fwSession->fwInstance, &i2);
  1079   if( CKR_OK != error ) {
  1080     return error;
  1083   /*
  1084    * Add a little integrety/identity check.  
  1085    * NOTE: right now, it's pretty stupid.  
  1086    * A CRC or something would be better.
  1087    */
  1089   ulBuffer[0] = 0x434b4657; /* CKFW */
  1090   ulBuffer[1] = 0;
  1091   n = i2.size/sizeof(CK_ULONG);
  1092   for( i = 0; i < n; i++ ) {
  1093     ulBuffer[1] ^= ulBuffer[2+i];
  1096   return CKR_OK;
  1099 /*
  1100  * nssCKFWSession_SetOperationState
  1102  */
  1103 NSS_IMPLEMENT CK_RV
  1104 nssCKFWSession_SetOperationState
  1106   NSSCKFWSession *fwSession,
  1107   NSSItem *state,
  1108   NSSCKFWObject *encryptionKey,
  1109   NSSCKFWObject *authenticationKey
  1112   CK_RV error = CKR_OK;
  1113   CK_ULONG *ulBuffer;
  1114   CK_ULONG n, i;
  1115   CK_ULONG x;
  1116   NSSItem s;
  1117   NSSCKMDObject *mdek;
  1118   NSSCKMDObject *mdak;
  1120 #ifdef NSSDEBUG
  1121   error = nssCKFWSession_verifyPointer(fwSession);
  1122   if( CKR_OK != error ) {
  1123     return error;
  1126   if (!state) {
  1127     return CKR_ARGUMENTS_BAD;
  1130   if (!state->data) {
  1131     return CKR_ARGUMENTS_BAD;
  1134   if (encryptionKey) {
  1135     error = nssCKFWObject_verifyPointer(encryptionKey);
  1136     if( CKR_OK != error ) {
  1137       return error;
  1141   if (authenticationKey) {
  1142     error = nssCKFWObject_verifyPointer(authenticationKey);
  1143     if( CKR_OK != error ) {
  1144       return error;
  1148   if (!fwSession->mdSession) {
  1149     return CKR_GENERAL_ERROR;
  1151 #endif /* NSSDEBUG */
  1153   ulBuffer = (CK_ULONG *)state->data;
  1154   if( 0x43b4657 != ulBuffer[0] ) {
  1155     return CKR_SAVED_STATE_INVALID;
  1157   n = (state->size / sizeof(CK_ULONG)) - 2;
  1158   x = (CK_ULONG)0;
  1159   for( i = 0; i < n; i++ ) {
  1160     x ^= ulBuffer[2+i];
  1163   if( x != ulBuffer[1] ) {
  1164     return CKR_SAVED_STATE_INVALID;
  1167   if (!fwSession->mdSession->SetOperationState) {
  1168     return CKR_GENERAL_ERROR;
  1171   s.size = state->size - 2*sizeof(CK_ULONG);
  1172   s.data = (void *)&ulBuffer[2];
  1174   if (encryptionKey) {
  1175     mdek = nssCKFWObject_GetMDObject(encryptionKey);
  1176   } else {
  1177     mdek = (NSSCKMDObject *)NULL;
  1180   if (authenticationKey) {
  1181     mdak = nssCKFWObject_GetMDObject(authenticationKey);
  1182   } else {
  1183     mdak = (NSSCKMDObject *)NULL;
  1186   error = fwSession->mdSession->SetOperationState(fwSession->mdSession, 
  1187     fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  1188     fwSession->fwInstance, &s, mdek, encryptionKey, mdak, authenticationKey);
  1190   if( CKR_OK != error ) {
  1191     return error;
  1194   /*
  1195    * Here'd we restore any session data
  1196    */
  1198   return CKR_OK;
  1201 static CK_BBOOL
  1202 nss_attributes_form_token_object
  1204   CK_ATTRIBUTE_PTR pTemplate,
  1205   CK_ULONG ulAttributeCount
  1208   CK_ULONG i;
  1209   CK_BBOOL rv;
  1211   for( i = 0; i < ulAttributeCount; i++ ) {
  1212     if( CKA_TOKEN == pTemplate[i].type ) {
  1213       /* If we sanity-check, we can remove this sizeof check */
  1214       if( sizeof(CK_BBOOL) == pTemplate[i].ulValueLen ) {
  1215         (void)nsslibc_memcpy(&rv, pTemplate[i].pValue, sizeof(CK_BBOOL));
  1216         return rv;
  1217       } else {
  1218         return CK_FALSE;
  1223   return CK_FALSE;
  1226 /*
  1227  * nssCKFWSession_CreateObject
  1229  */
  1230 NSS_IMPLEMENT NSSCKFWObject *
  1231 nssCKFWSession_CreateObject
  1233   NSSCKFWSession *fwSession,
  1234   CK_ATTRIBUTE_PTR pTemplate,
  1235   CK_ULONG ulAttributeCount,
  1236   CK_RV *pError
  1239   NSSArena *arena;
  1240   NSSCKMDObject *mdObject;
  1241   NSSCKFWObject *fwObject;
  1242   CK_BBOOL isTokenObject;
  1244 #ifdef NSSDEBUG
  1245   if (!pError) {
  1246     return (NSSCKFWObject *)NULL;
  1249   *pError = nssCKFWSession_verifyPointer(fwSession);
  1250   if( CKR_OK != pError ) {
  1251     return (NSSCKFWObject *)NULL;
  1254   if( (CK_ATTRIBUTE_PTR)NULL == pTemplate ) {
  1255     *pError = CKR_ARGUMENTS_BAD;
  1256     return (NSSCKFWObject *)NULL;
  1259   if (!fwSession->mdSession) {
  1260     *pError = CKR_GENERAL_ERROR;
  1261     return (NSSCKFWObject *)NULL;
  1263 #endif /* NSSDEBUG */
  1265   /*
  1266    * Here would be an excellent place to sanity-check the object.
  1267    */
  1269   isTokenObject = nss_attributes_form_token_object(pTemplate, ulAttributeCount);
  1270   if( CK_TRUE == isTokenObject ) {
  1271     /* === TOKEN OBJECT === */
  1273     if (!fwSession->mdSession->CreateObject) {
  1274       *pError = CKR_TOKEN_WRITE_PROTECTED;
  1275       return (NSSCKFWObject *)NULL;
  1278     arena = nssCKFWToken_GetArena(fwSession->fwToken, pError);
  1279     if (!arena) {
  1280       if( CKR_OK == *pError ) {
  1281         *pError = CKR_GENERAL_ERROR;
  1283       return (NSSCKFWObject *)NULL;
  1286     goto callmdcreateobject;
  1287   } else {
  1288     /* === SESSION OBJECT === */
  1290     arena = nssCKFWSession_GetArena(fwSession, pError);
  1291     if (!arena) {
  1292       if( CKR_OK == *pError ) {
  1293         *pError = CKR_GENERAL_ERROR;
  1295       return (NSSCKFWObject *)NULL;
  1298     if( CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects(
  1299                      fwSession->fwInstance) ) {
  1300       /* --- module handles the session object -- */
  1302       if (!fwSession->mdSession->CreateObject) {
  1303         *pError = CKR_GENERAL_ERROR;
  1304         return (NSSCKFWObject *)NULL;
  1307       goto callmdcreateobject;
  1308     } else {
  1309       /* --- framework handles the session object -- */
  1310       mdObject = nssCKMDSessionObject_Create(fwSession->fwToken, 
  1311         arena, pTemplate, ulAttributeCount, pError);
  1312       goto gotmdobject;
  1316  callmdcreateobject:
  1317   mdObject = fwSession->mdSession->CreateObject(fwSession->mdSession,
  1318     fwSession, fwSession->mdToken, fwSession->fwToken,
  1319     fwSession->mdInstance, fwSession->fwInstance, arena, pTemplate,
  1320     ulAttributeCount, pError);
  1322  gotmdobject:
  1323   if (!mdObject) {
  1324     if( CKR_OK == *pError ) {
  1325       *pError = CKR_GENERAL_ERROR;
  1327     return (NSSCKFWObject *)NULL;
  1330   fwObject = nssCKFWObject_Create(arena, mdObject, 
  1331     isTokenObject ? NULL : fwSession, 
  1332     fwSession->fwToken, fwSession->fwInstance, pError);
  1333   if (!fwObject) {
  1334     if( CKR_OK == *pError ) {
  1335       *pError = CKR_GENERAL_ERROR;
  1338     if (mdObject->Destroy) {
  1339       (void)mdObject->Destroy(mdObject, (NSSCKFWObject *)NULL,
  1340         fwSession->mdSession, fwSession, fwSession->mdToken,
  1341         fwSession->fwToken, fwSession->mdInstance, fwSession->fwInstance);
  1344     return (NSSCKFWObject *)NULL;
  1347   if( CK_FALSE == isTokenObject ) {
  1348     if( CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, fwObject) ) {
  1349       *pError = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject);
  1350       if( CKR_OK != *pError ) {
  1351         nssCKFWObject_Finalize(fwObject, PR_TRUE);
  1352         return (NSSCKFWObject *)NULL;
  1357   return fwObject;
  1360 /*
  1361  * nssCKFWSession_CopyObject
  1363  */
  1364 NSS_IMPLEMENT NSSCKFWObject *
  1365 nssCKFWSession_CopyObject
  1367   NSSCKFWSession *fwSession,
  1368   NSSCKFWObject *fwObject,
  1369   CK_ATTRIBUTE_PTR pTemplate,
  1370   CK_ULONG ulAttributeCount,
  1371   CK_RV *pError
  1374   CK_BBOOL oldIsToken;
  1375   CK_BBOOL newIsToken;
  1376   CK_ULONG i;
  1377   NSSCKFWObject *rv;
  1379 #ifdef NSSDEBUG
  1380   if (!pError) {
  1381     return (NSSCKFWObject *)NULL;
  1384   *pError = nssCKFWSession_verifyPointer(fwSession);
  1385   if( CKR_OK != *pError ) {
  1386     return (NSSCKFWObject *)NULL;
  1389   *pError = nssCKFWObject_verifyPointer(fwObject);
  1390   if( CKR_OK != *pError ) {
  1391     return (NSSCKFWObject *)NULL;
  1394   if (!fwSession->mdSession) {
  1395     *pError = CKR_GENERAL_ERROR;
  1396     return (NSSCKFWObject *)NULL;
  1398 #endif /* NSSDEBUG */
  1400   /*
  1401    * Sanity-check object
  1402    */
  1404   if (!fwObject) {
  1405     *pError = CKR_ARGUMENTS_BAD;
  1406     return (NSSCKFWObject *)NULL;
  1409   oldIsToken = nssCKFWObject_IsTokenObject(fwObject);
  1411   newIsToken = oldIsToken;
  1412   for( i = 0; i < ulAttributeCount; i++ ) {
  1413     if( CKA_TOKEN == pTemplate[i].type ) {
  1414       /* Since we sanity-checked the object, we know this is the right size. */
  1415       (void)nsslibc_memcpy(&newIsToken, pTemplate[i].pValue, sizeof(CK_BBOOL));
  1416       break;
  1420   /*
  1421    * If the Module handles its session objects, or if both the new
  1422    * and old object are token objects, use CopyObject if it exists.
  1423    */
  1425   if ((fwSession->mdSession->CopyObject) &&
  1426       (((CK_TRUE == oldIsToken) && (CK_TRUE == newIsToken)) ||
  1427        (CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects(
  1428                      fwSession->fwInstance))) ) {
  1429     /* use copy object */
  1430     NSSArena *arena;
  1431     NSSCKMDObject *mdOldObject;
  1432     NSSCKMDObject *mdObject;
  1434     mdOldObject = nssCKFWObject_GetMDObject(fwObject);
  1436     if( CK_TRUE == newIsToken ) {
  1437       arena = nssCKFWToken_GetArena(fwSession->fwToken, pError);
  1438     } else {
  1439       arena = nssCKFWSession_GetArena(fwSession, pError);
  1441     if (!arena) {
  1442       if( CKR_OK == *pError ) {
  1443         *pError = CKR_GENERAL_ERROR;
  1445       return (NSSCKFWObject *)NULL;
  1448     mdObject = fwSession->mdSession->CopyObject(fwSession->mdSession,
  1449       fwSession, fwSession->mdToken, fwSession->fwToken,
  1450       fwSession->mdInstance, fwSession->fwInstance, mdOldObject,
  1451       fwObject, arena, pTemplate, ulAttributeCount, pError);
  1452     if (!mdObject) {
  1453       if( CKR_OK == *pError ) {
  1454         *pError = CKR_GENERAL_ERROR;
  1456       return (NSSCKFWObject *)NULL;
  1459     rv = nssCKFWObject_Create(arena, mdObject, 
  1460       newIsToken ? NULL : fwSession,
  1461       fwSession->fwToken, fwSession->fwInstance, pError);
  1463     if( CK_FALSE == newIsToken ) {
  1464       if( CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, rv) ) {
  1465         *pError = nssCKFWHash_Add(fwSession->sessionObjectHash, rv, rv);
  1466         if( CKR_OK != *pError ) {
  1467           nssCKFWObject_Finalize(rv, PR_TRUE);
  1468           return (NSSCKFWObject *)NULL;
  1473     return rv;
  1474   } else {
  1475     /* use create object */
  1476     NSSArena *tmpArena;
  1477     CK_ATTRIBUTE_PTR newTemplate;
  1478     CK_ULONG i, j, n, newLength, k;
  1479     CK_ATTRIBUTE_TYPE_PTR oldTypes;
  1480     NSSCKFWObject *rv;
  1482     n = nssCKFWObject_GetAttributeCount(fwObject, pError);
  1483     if( (0 == n) && (CKR_OK != *pError) ) {
  1484       return (NSSCKFWObject *)NULL;
  1487     tmpArena = NSSArena_Create();
  1488     if (!tmpArena) {
  1489       *pError = CKR_HOST_MEMORY;
  1490       return (NSSCKFWObject *)NULL;
  1493     oldTypes = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE_TYPE, n);
  1494     if( (CK_ATTRIBUTE_TYPE_PTR)NULL == oldTypes ) {
  1495       NSSArena_Destroy(tmpArena);
  1496       *pError = CKR_HOST_MEMORY;
  1497       return (NSSCKFWObject *)NULL;
  1500     *pError = nssCKFWObject_GetAttributeTypes(fwObject, oldTypes, n);
  1501     if( CKR_OK != *pError ) {
  1502       NSSArena_Destroy(tmpArena);
  1503       return (NSSCKFWObject *)NULL;
  1506     newLength = n;
  1507     for( i = 0; i < ulAttributeCount; i++ ) {
  1508       for( j = 0; j < n; j++ ) {
  1509         if( oldTypes[j] == pTemplate[i].type ) {
  1510           if( (CK_VOID_PTR)NULL == pTemplate[i].pValue ) {
  1511             /* Removing the attribute */
  1512             newLength--;
  1514           break;
  1517       if( j == n ) {
  1518         /* Not found */
  1519         newLength++;
  1523     newTemplate = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE, newLength);
  1524     if( (CK_ATTRIBUTE_PTR)NULL == newTemplate ) {
  1525       NSSArena_Destroy(tmpArena);
  1526       *pError = CKR_HOST_MEMORY;
  1527       return (NSSCKFWObject *)NULL;
  1530     k = 0;
  1531     for( j = 0; j < n; j++ ) {
  1532       for( i = 0; i < ulAttributeCount; i++ ) {
  1533         if( oldTypes[j] == pTemplate[i].type ) {
  1534           if( (CK_VOID_PTR)NULL == pTemplate[i].pValue ) {
  1535             /* This attribute is being deleted */
  1537           } else {
  1538             /* This attribute is being replaced */
  1539             newTemplate[k].type = pTemplate[i].type;
  1540             newTemplate[k].pValue = pTemplate[i].pValue;
  1541             newTemplate[k].ulValueLen = pTemplate[i].ulValueLen;
  1542             k++;
  1544           break;
  1547       if( i == ulAttributeCount ) {
  1548         /* This attribute is being copied over from the old object */
  1549         NSSItem item, *it;
  1550         item.size = 0;
  1551         item.data = (void *)NULL;
  1552         it = nssCKFWObject_GetAttribute(fwObject, oldTypes[j],
  1553           &item, tmpArena, pError);
  1554         if (!it) {
  1555           if( CKR_OK == *pError ) {
  1556             *pError = CKR_GENERAL_ERROR;
  1558           NSSArena_Destroy(tmpArena);
  1559           return (NSSCKFWObject *)NULL;
  1561         newTemplate[k].type = oldTypes[j];
  1562         newTemplate[k].pValue = it->data;
  1563         newTemplate[k].ulValueLen = it->size;
  1564         k++;
  1567     /* assert that k == newLength */
  1569     rv = nssCKFWSession_CreateObject(fwSession, newTemplate, newLength, pError);
  1570     if (!rv) {
  1571       if( CKR_OK == *pError ) {
  1572         *pError = CKR_GENERAL_ERROR;
  1574       NSSArena_Destroy(tmpArena);
  1575       return (NSSCKFWObject *)NULL;
  1578     NSSArena_Destroy(tmpArena);
  1579     return rv;
  1583 /*
  1584  * nssCKFWSession_FindObjectsInit
  1586  */
  1587 NSS_IMPLEMENT NSSCKFWFindObjects *
  1588 nssCKFWSession_FindObjectsInit
  1590   NSSCKFWSession *fwSession,
  1591   CK_ATTRIBUTE_PTR pTemplate,
  1592   CK_ULONG ulAttributeCount,
  1593   CK_RV *pError
  1596   NSSCKMDFindObjects *mdfo1 = (NSSCKMDFindObjects *)NULL;
  1597   NSSCKMDFindObjects *mdfo2 = (NSSCKMDFindObjects *)NULL;
  1599 #ifdef NSSDEBUG
  1600   if (!pError) {
  1601     return (NSSCKFWFindObjects *)NULL;
  1604   *pError = nssCKFWSession_verifyPointer(fwSession);
  1605   if( CKR_OK != *pError ) {
  1606     return (NSSCKFWFindObjects *)NULL;
  1609   if( ((CK_ATTRIBUTE_PTR)NULL == pTemplate) && (ulAttributeCount != 0) ) {
  1610     *pError = CKR_ARGUMENTS_BAD;
  1611     return (NSSCKFWFindObjects *)NULL;
  1614   if (!fwSession->mdSession) {
  1615     *pError = CKR_GENERAL_ERROR;
  1616     return (NSSCKFWFindObjects *)NULL;
  1618 #endif /* NSSDEBUG */
  1620   if( CK_TRUE != nssCKFWInstance_GetModuleHandlesSessionObjects(
  1621                    fwSession->fwInstance) ) {
  1622     CK_ULONG i;
  1624     /*
  1625      * Does the search criteria restrict us to token or session
  1626      * objects?
  1627      */
  1629     for( i = 0; i < ulAttributeCount; i++ ) {
  1630       if( CKA_TOKEN == pTemplate[i].type ) {
  1631         /* Yes, it does. */
  1632         CK_BBOOL isToken;
  1633         if( sizeof(CK_BBOOL) != pTemplate[i].ulValueLen ) {
  1634           *pError = CKR_ATTRIBUTE_VALUE_INVALID;
  1635           return (NSSCKFWFindObjects *)NULL;
  1637         (void)nsslibc_memcpy(&isToken, pTemplate[i].pValue, sizeof(CK_BBOOL));
  1639         if( CK_TRUE == isToken ) {
  1640           /* Pass it on to the module's search routine */
  1641           if (!fwSession->mdSession->FindObjectsInit) {
  1642             goto wrap;
  1645           mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
  1646                     fwSession, fwSession->mdToken, fwSession->fwToken,
  1647                     fwSession->mdInstance, fwSession->fwInstance, 
  1648                     pTemplate, ulAttributeCount, pError);
  1649         } else {
  1650           /* Do the search ourselves */
  1651           mdfo1 = nssCKMDFindSessionObjects_Create(fwSession->fwToken, 
  1652                     pTemplate, ulAttributeCount, pError);
  1655         if (!mdfo1) {
  1656           if( CKR_OK == *pError ) {
  1657             *pError = CKR_GENERAL_ERROR;
  1659           return (NSSCKFWFindObjects *)NULL;
  1662         goto wrap;
  1666     if( i == ulAttributeCount ) {
  1667       /* No, it doesn't.  Do a hybrid search. */
  1668       mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
  1669                 fwSession, fwSession->mdToken, fwSession->fwToken,
  1670                 fwSession->mdInstance, fwSession->fwInstance, 
  1671                 pTemplate, ulAttributeCount, pError);
  1673       if (!mdfo1) {
  1674         if( CKR_OK == *pError ) {
  1675           *pError = CKR_GENERAL_ERROR;
  1677         return (NSSCKFWFindObjects *)NULL;
  1680       mdfo2 = nssCKMDFindSessionObjects_Create(fwSession->fwToken,
  1681                 pTemplate, ulAttributeCount, pError);
  1682       if (!mdfo2) {
  1683         if( CKR_OK == *pError ) {
  1684           *pError = CKR_GENERAL_ERROR;
  1686         if (mdfo1->Final) {
  1687           mdfo1->Final(mdfo1, (NSSCKFWFindObjects *)NULL, fwSession->mdSession,
  1688             fwSession, fwSession->mdToken, fwSession->fwToken, 
  1689             fwSession->mdInstance, fwSession->fwInstance);
  1691         return (NSSCKFWFindObjects *)NULL;
  1694       goto wrap;
  1696     /*NOTREACHED*/
  1697   } else {
  1698     /* Module handles all its own objects.  Pass on to module's search */
  1699     mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
  1700               fwSession, fwSession->mdToken, fwSession->fwToken,
  1701               fwSession->mdInstance, fwSession->fwInstance, 
  1702               pTemplate, ulAttributeCount, pError);
  1704     if (!mdfo1) {
  1705       if( CKR_OK == *pError ) {
  1706         *pError = CKR_GENERAL_ERROR;
  1708       return (NSSCKFWFindObjects *)NULL;
  1711     goto wrap;
  1714  wrap:
  1715   return nssCKFWFindObjects_Create(fwSession, fwSession->fwToken,
  1716            fwSession->fwInstance, mdfo1, mdfo2, pError);
  1719 /*
  1720  * nssCKFWSession_SeedRandom
  1722  */
  1723 NSS_IMPLEMENT CK_RV
  1724 nssCKFWSession_SeedRandom
  1726   NSSCKFWSession *fwSession,
  1727   NSSItem *seed
  1730   CK_RV error = CKR_OK;
  1732 #ifdef NSSDEBUG
  1733   error = nssCKFWSession_verifyPointer(fwSession);
  1734   if( CKR_OK != error ) {
  1735     return error;
  1738   if (!seed) {
  1739     return CKR_ARGUMENTS_BAD;
  1742   if (!seed->data) {
  1743     return CKR_ARGUMENTS_BAD;
  1746   if( 0 == seed->size ) {
  1747     return CKR_ARGUMENTS_BAD;
  1750   if (!fwSession->mdSession) {
  1751     return CKR_GENERAL_ERROR;
  1753 #endif /* NSSDEBUG */
  1755   if (!fwSession->mdSession->SeedRandom) {
  1756     return CKR_RANDOM_SEED_NOT_SUPPORTED;
  1759   error = fwSession->mdSession->SeedRandom(fwSession->mdSession, fwSession,
  1760     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  1761     fwSession->fwInstance, seed);
  1763   return error;
  1766 /*
  1767  * nssCKFWSession_GetRandom
  1769  */
  1770 NSS_IMPLEMENT CK_RV
  1771 nssCKFWSession_GetRandom
  1773   NSSCKFWSession *fwSession,
  1774   NSSItem *buffer
  1777   CK_RV error = CKR_OK;
  1779 #ifdef NSSDEBUG
  1780   error = nssCKFWSession_verifyPointer(fwSession);
  1781   if( CKR_OK != error ) {
  1782     return error;
  1785   if (!buffer) {
  1786     return CKR_ARGUMENTS_BAD;
  1789   if (!buffer->data) {
  1790     return CKR_ARGUMENTS_BAD;
  1793   if (!fwSession->mdSession) {
  1794     return CKR_GENERAL_ERROR;
  1796 #endif /* NSSDEBUG */
  1798   if (!fwSession->mdSession->GetRandom) {
  1799     if( CK_TRUE == nssCKFWToken_GetHasRNG(fwSession->fwToken) ) {
  1800       return CKR_GENERAL_ERROR;
  1801     } else {
  1802       return CKR_RANDOM_NO_RNG;
  1806   if( 0 == buffer->size ) {
  1807     return CKR_OK;
  1810   error = fwSession->mdSession->GetRandom(fwSession->mdSession, fwSession,
  1811     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  1812     fwSession->fwInstance, buffer);
  1814   return error;
  1818 /*
  1819  * nssCKFWSession_SetCurrentCryptoOperation
  1820  */
  1821 NSS_IMPLEMENT void
  1822 nssCKFWSession_SetCurrentCryptoOperation
  1824   NSSCKFWSession *fwSession,
  1825   NSSCKFWCryptoOperation * fwOperation,
  1826   NSSCKFWCryptoOperationState state
  1829 #ifdef NSSDEBUG
  1830   CK_RV error = CKR_OK;
  1831   error = nssCKFWSession_verifyPointer(fwSession);
  1832   if( CKR_OK != error ) {
  1833     return;
  1836   if ( state >= NSSCKFWCryptoOperationState_Max) {
  1837     return;
  1840   if (!fwSession->mdSession) {
  1841     return;
  1843 #endif /* NSSDEBUG */
  1844   fwSession->fwOperationArray[state] = fwOperation;
  1845   return;
  1848 /*
  1849  * nssCKFWSession_GetCurrentCryptoOperation
  1850  */
  1851 NSS_IMPLEMENT NSSCKFWCryptoOperation *
  1852 nssCKFWSession_GetCurrentCryptoOperation
  1854   NSSCKFWSession *fwSession,
  1855   NSSCKFWCryptoOperationState state
  1858 #ifdef NSSDEBUG
  1859   CK_RV error = CKR_OK;
  1860   error = nssCKFWSession_verifyPointer(fwSession);
  1861   if( CKR_OK != error ) {
  1862     return (NSSCKFWCryptoOperation *)NULL;
  1865   if ( state >= NSSCKFWCryptoOperationState_Max) {
  1866     return (NSSCKFWCryptoOperation *)NULL;
  1869   if (!fwSession->mdSession) {
  1870     return (NSSCKFWCryptoOperation *)NULL;
  1872 #endif /* NSSDEBUG */
  1873   return fwSession->fwOperationArray[state];
  1876 /*
  1877  * nssCKFWSession_Final
  1878  */
  1879 NSS_IMPLEMENT CK_RV
  1880 nssCKFWSession_Final
  1882   NSSCKFWSession *fwSession,
  1883   NSSCKFWCryptoOperationType type,
  1884   NSSCKFWCryptoOperationState state,
  1885   CK_BYTE_PTR  outBuf,
  1886   CK_ULONG_PTR outBufLen
  1889   NSSCKFWCryptoOperation *fwOperation;
  1890   NSSItem outputBuffer;
  1891   CK_RV error = CKR_OK;
  1893 #ifdef NSSDEBUG
  1894   error = nssCKFWSession_verifyPointer(fwSession);
  1895   if( CKR_OK != error ) {
  1896     return error;
  1899   if (!fwSession->mdSession) {
  1900     return CKR_GENERAL_ERROR;
  1902 #endif /* NSSDEBUG */
  1904   /* make sure we have a valid operation initialized */
  1905   fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
  1906   if (!fwOperation) {
  1907     return CKR_OPERATION_NOT_INITIALIZED;
  1910   /* make sure it's the correct type */
  1911   if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
  1912     return CKR_OPERATION_NOT_INITIALIZED;
  1915   /* handle buffer issues, note for Verify, the type is an input buffer. */
  1916   if (NSSCKFWCryptoOperationType_Verify == type) {
  1917     if ((CK_BYTE_PTR)NULL == outBuf) {
  1918       error = CKR_ARGUMENTS_BAD;
  1919       goto done;
  1921   } else {
  1922     CK_ULONG len = nssCKFWCryptoOperation_GetFinalLength(fwOperation, &error);
  1923     CK_ULONG maxBufLen = *outBufLen;
  1925     if (CKR_OK != error) {
  1926        goto done;
  1928     *outBufLen = len;
  1929     if ((CK_BYTE_PTR)NULL == outBuf) {
  1930       return CKR_OK;
  1933     if (len > maxBufLen) {
  1934       return CKR_BUFFER_TOO_SMALL;
  1937   outputBuffer.data = outBuf;
  1938   outputBuffer.size = *outBufLen;
  1940   error = nssCKFWCryptoOperation_Final(fwOperation, &outputBuffer);
  1941 done:
  1942   if (CKR_BUFFER_TOO_SMALL == error) {
  1943     return error;
  1945   /* clean up our state */
  1946   nssCKFWCryptoOperation_Destroy(fwOperation);
  1947   nssCKFWSession_SetCurrentCryptoOperation(fwSession, NULL, state);
  1948   return error;
  1951 /*
  1952  * nssCKFWSession_Update
  1953  */
  1954 NSS_IMPLEMENT CK_RV
  1955 nssCKFWSession_Update
  1957   NSSCKFWSession *fwSession,
  1958   NSSCKFWCryptoOperationType type,
  1959   NSSCKFWCryptoOperationState state,
  1960   CK_BYTE_PTR  inBuf,
  1961   CK_ULONG     inBufLen,
  1962   CK_BYTE_PTR  outBuf,
  1963   CK_ULONG_PTR outBufLen
  1966   NSSCKFWCryptoOperation *fwOperation;
  1967   NSSItem inputBuffer;
  1968   NSSItem outputBuffer;
  1969   CK_ULONG len;
  1970   CK_ULONG maxBufLen;
  1971   CK_RV error = CKR_OK;
  1973 #ifdef NSSDEBUG
  1974   error = nssCKFWSession_verifyPointer(fwSession);
  1975   if( CKR_OK != error ) {
  1976     return error;
  1979   if (!fwSession->mdSession) {
  1980     return CKR_GENERAL_ERROR;
  1982 #endif /* NSSDEBUG */
  1984   /* make sure we have a valid operation initialized */
  1985   fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
  1986   if (!fwOperation) {
  1987     return CKR_OPERATION_NOT_INITIALIZED;
  1990   /* make sure it's the correct type */
  1991   if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
  1992     return CKR_OPERATION_NOT_INITIALIZED;
  1995   inputBuffer.data = inBuf;
  1996   inputBuffer.size = inBufLen;
  1998   /* handle buffer issues, note for Verify, the type is an input buffer. */
  1999   len = nssCKFWCryptoOperation_GetOperationLength(fwOperation, &inputBuffer, 
  2000                                                   &error);
  2001   if (CKR_OK != error) {
  2002     return error;
  2004   maxBufLen = *outBufLen;
  2006   *outBufLen = len;
  2007   if ((CK_BYTE_PTR)NULL == outBuf) {
  2008     return CKR_OK;
  2011   if (len > maxBufLen) {
  2012     return CKR_BUFFER_TOO_SMALL;
  2014   outputBuffer.data = outBuf;
  2015   outputBuffer.size = *outBufLen;
  2017   return nssCKFWCryptoOperation_Update(fwOperation,
  2018                                        &inputBuffer, &outputBuffer);
  2021 /*
  2022  * nssCKFWSession_DigestUpdate
  2023  */
  2024 NSS_IMPLEMENT CK_RV
  2025 nssCKFWSession_DigestUpdate
  2027   NSSCKFWSession *fwSession,
  2028   NSSCKFWCryptoOperationType type,
  2029   NSSCKFWCryptoOperationState state,
  2030   CK_BYTE_PTR  inBuf,
  2031   CK_ULONG     inBufLen
  2034   NSSCKFWCryptoOperation *fwOperation;
  2035   NSSItem inputBuffer;
  2036   CK_RV error = CKR_OK;
  2038 #ifdef NSSDEBUG
  2039   error = nssCKFWSession_verifyPointer(fwSession);
  2040   if( CKR_OK != error ) {
  2041     return error;
  2044   if (!fwSession->mdSession) {
  2045     return CKR_GENERAL_ERROR;
  2047 #endif /* NSSDEBUG */
  2049   /* make sure we have a valid operation initialized */
  2050   fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
  2051   if (!fwOperation) {
  2052     return CKR_OPERATION_NOT_INITIALIZED;
  2055   /* make sure it's the correct type */
  2056   if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
  2057     return CKR_OPERATION_NOT_INITIALIZED;
  2060   inputBuffer.data = inBuf;
  2061   inputBuffer.size = inBufLen;
  2064   error = nssCKFWCryptoOperation_DigestUpdate(fwOperation, &inputBuffer);
  2065   return error;
  2068 /*
  2069  * nssCKFWSession_DigestUpdate
  2070  */
  2071 NSS_IMPLEMENT CK_RV
  2072 nssCKFWSession_DigestKey
  2074   NSSCKFWSession *fwSession,
  2075   NSSCKFWObject *fwKey
  2078   NSSCKFWCryptoOperation *fwOperation;
  2079   NSSItem *inputBuffer;
  2080   CK_RV error = CKR_OK;
  2082 #ifdef NSSDEBUG
  2083   error = nssCKFWSession_verifyPointer(fwSession);
  2084   if( CKR_OK != error ) {
  2085     return error;
  2088   if (!fwSession->mdSession) {
  2089     return CKR_GENERAL_ERROR;
  2091 #endif /* NSSDEBUG */
  2093   /* make sure we have a valid operation initialized */
  2094   fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, 
  2095                                  NSSCKFWCryptoOperationState_Digest);
  2096   if (!fwOperation) {
  2097     return CKR_OPERATION_NOT_INITIALIZED;
  2100   /* make sure it's the correct type */
  2101   if (NSSCKFWCryptoOperationType_Digest != 
  2102       nssCKFWCryptoOperation_GetType(fwOperation)) {
  2103     return CKR_OPERATION_NOT_INITIALIZED;
  2106   error = nssCKFWCryptoOperation_DigestKey(fwOperation, fwKey);
  2107   if (CKR_FUNCTION_FAILED != error) {
  2108     return error;
  2111   /* no machine depended way for this to happen, do it by hand */
  2112   inputBuffer=nssCKFWObject_GetAttribute(fwKey, CKA_VALUE, NULL, NULL, &error);
  2113   if (!inputBuffer) {
  2114     /* couldn't get the value, just fail then */
  2115     return error;
  2117   error = nssCKFWCryptoOperation_DigestUpdate(fwOperation, inputBuffer);
  2118   nssItem_Destroy(inputBuffer);
  2119   return error;
  2122 /*
  2123  * nssCKFWSession_UpdateFinal
  2124  */
  2125 NSS_IMPLEMENT CK_RV
  2126 nssCKFWSession_UpdateFinal
  2128   NSSCKFWSession *fwSession,
  2129   NSSCKFWCryptoOperationType type,
  2130   NSSCKFWCryptoOperationState state,
  2131   CK_BYTE_PTR  inBuf,
  2132   CK_ULONG     inBufLen,
  2133   CK_BYTE_PTR  outBuf,
  2134   CK_ULONG_PTR outBufLen
  2137   NSSCKFWCryptoOperation *fwOperation;
  2138   NSSItem inputBuffer;
  2139   NSSItem outputBuffer;
  2140   PRBool isEncryptDecrypt;
  2141   CK_RV error = CKR_OK;
  2143 #ifdef NSSDEBUG
  2144   error = nssCKFWSession_verifyPointer(fwSession);
  2145   if( CKR_OK != error ) {
  2146     return error;
  2149   if (!fwSession->mdSession) {
  2150     return CKR_GENERAL_ERROR;
  2152 #endif /* NSSDEBUG */
  2154   /* make sure we have a valid operation initialized */
  2155   fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
  2156   if (!fwOperation) {
  2157     return CKR_OPERATION_NOT_INITIALIZED;
  2160   /* make sure it's the correct type */
  2161   if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
  2162     return CKR_OPERATION_NOT_INITIALIZED;
  2165   inputBuffer.data = inBuf;
  2166   inputBuffer.size = inBufLen;
  2167   isEncryptDecrypt = (PRBool) ((NSSCKFWCryptoOperationType_Encrypt == type) || 
  2168                                (NSSCKFWCryptoOperationType_Decrypt == type)) ;
  2170   /* handle buffer issues, note for Verify, the type is an input buffer. */
  2171   if (NSSCKFWCryptoOperationType_Verify == type) {
  2172     if ((CK_BYTE_PTR)NULL == outBuf) {
  2173       error = CKR_ARGUMENTS_BAD;
  2174       goto done;
  2176   } else {
  2177     CK_ULONG maxBufLen = *outBufLen;
  2178     CK_ULONG len;
  2180     len = (isEncryptDecrypt) ?
  2181       nssCKFWCryptoOperation_GetOperationLength(fwOperation, 
  2182                                                 &inputBuffer, &error) :
  2183       nssCKFWCryptoOperation_GetFinalLength(fwOperation, &error);
  2185     if (CKR_OK != error) {
  2186       goto done;
  2189     *outBufLen = len;
  2190     if ((CK_BYTE_PTR)NULL == outBuf) {
  2191       return CKR_OK;
  2194     if (len > maxBufLen) {
  2195       return CKR_BUFFER_TOO_SMALL;
  2198   outputBuffer.data = outBuf;
  2199   outputBuffer.size = *outBufLen;
  2201   error = nssCKFWCryptoOperation_UpdateFinal(fwOperation, 
  2202                                              &inputBuffer, &outputBuffer);
  2204   /* UpdateFinal isn't support, manually use Update and Final */
  2205   if (CKR_FUNCTION_FAILED == error) {
  2206     error = isEncryptDecrypt ? 
  2207       nssCKFWCryptoOperation_Update(fwOperation, &inputBuffer, &outputBuffer) :
  2208       nssCKFWCryptoOperation_DigestUpdate(fwOperation, &inputBuffer);
  2210     if (CKR_OK == error) {
  2211       error = nssCKFWCryptoOperation_Final(fwOperation, &outputBuffer);
  2216 done:
  2217   if (CKR_BUFFER_TOO_SMALL == error) {
  2218     /* if we return CKR_BUFFER_TOO_SMALL, we the caller is not expecting.
  2219      * the crypto state to be freed */
  2220     return error;
  2223   /* clean up our state */
  2224   nssCKFWCryptoOperation_Destroy(fwOperation);
  2225   nssCKFWSession_SetCurrentCryptoOperation(fwSession, NULL, state);
  2226   return error;
  2229 NSS_IMPLEMENT CK_RV
  2230 nssCKFWSession_UpdateCombo
  2232   NSSCKFWSession *fwSession,
  2233   NSSCKFWCryptoOperationType encryptType,
  2234   NSSCKFWCryptoOperationType digestType,
  2235   NSSCKFWCryptoOperationState digestState,
  2236   CK_BYTE_PTR  inBuf,
  2237   CK_ULONG     inBufLen,
  2238   CK_BYTE_PTR  outBuf,
  2239   CK_ULONG_PTR outBufLen
  2242   NSSCKFWCryptoOperation *fwOperation;
  2243   NSSCKFWCryptoOperation *fwPeerOperation;
  2244   NSSItem inputBuffer;
  2245   NSSItem outputBuffer;
  2246   CK_ULONG maxBufLen = *outBufLen;
  2247   CK_ULONG len;
  2248   CK_RV error = CKR_OK;
  2250 #ifdef NSSDEBUG
  2251   error = nssCKFWSession_verifyPointer(fwSession);
  2252   if( CKR_OK != error ) {
  2253     return error;
  2256   if (!fwSession->mdSession) {
  2257     return CKR_GENERAL_ERROR;
  2259 #endif /* NSSDEBUG */
  2261   /* make sure we have a valid operation initialized */
  2262   fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, 
  2263                 NSSCKFWCryptoOperationState_EncryptDecrypt);
  2264   if (!fwOperation) {
  2265     return CKR_OPERATION_NOT_INITIALIZED;
  2268   /* make sure it's the correct type */
  2269   if (encryptType != nssCKFWCryptoOperation_GetType(fwOperation)) {
  2270     return CKR_OPERATION_NOT_INITIALIZED;
  2272   /* make sure we have a valid operation initialized */
  2273   fwPeerOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, 
  2274                   digestState);
  2275   if (!fwPeerOperation) {
  2276     return CKR_OPERATION_NOT_INITIALIZED;
  2279   /* make sure it's the correct type */
  2280   if (digestType != nssCKFWCryptoOperation_GetType(fwOperation)) {
  2281     return CKR_OPERATION_NOT_INITIALIZED;
  2284   inputBuffer.data = inBuf;
  2285   inputBuffer.size = inBufLen;
  2286   len = nssCKFWCryptoOperation_GetOperationLength(fwOperation, 
  2287                                                 &inputBuffer, &error);
  2288   if (CKR_OK != error) {
  2289     return error;
  2292   *outBufLen = len;
  2293   if ((CK_BYTE_PTR)NULL == outBuf) {
  2294     return CKR_OK;
  2297   if (len > maxBufLen) {
  2298     return CKR_BUFFER_TOO_SMALL;
  2301   outputBuffer.data = outBuf;
  2302   outputBuffer.size = *outBufLen;
  2304   error = nssCKFWCryptoOperation_UpdateCombo(fwOperation, fwPeerOperation,
  2305                                              &inputBuffer, &outputBuffer);
  2306   if (CKR_FUNCTION_FAILED == error) {
  2307     PRBool isEncrypt = 
  2308            (PRBool) (NSSCKFWCryptoOperationType_Encrypt == encryptType);
  2310     if (isEncrypt) {
  2311       error = nssCKFWCryptoOperation_DigestUpdate(fwPeerOperation, 
  2312                                                   &inputBuffer);
  2313       if (CKR_OK != error) {
  2314         return error;
  2317     error = nssCKFWCryptoOperation_Update(fwOperation, 
  2318                                           &inputBuffer, &outputBuffer);
  2319     if (CKR_OK != error) {
  2320       return error;
  2322     if (!isEncrypt) {
  2323       error = nssCKFWCryptoOperation_DigestUpdate(fwPeerOperation,
  2324                                                   &outputBuffer);
  2327   return error;
  2331 /*
  2332  * NSSCKFWSession_GetMDSession
  2334  */
  2336 NSS_IMPLEMENT NSSCKMDSession *
  2337 NSSCKFWSession_GetMDSession
  2339   NSSCKFWSession *fwSession
  2342 #ifdef DEBUG
  2343   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  2344     return (NSSCKMDSession *)NULL;
  2346 #endif /* DEBUG */
  2348   return nssCKFWSession_GetMDSession(fwSession);
  2351 /*
  2352  * NSSCKFWSession_GetArena
  2354  */
  2356 NSS_IMPLEMENT NSSArena *
  2357 NSSCKFWSession_GetArena
  2359   NSSCKFWSession *fwSession,
  2360   CK_RV *pError
  2363 #ifdef DEBUG
  2364   if (!pError) {
  2365     return (NSSArena *)NULL;
  2368   *pError = nssCKFWSession_verifyPointer(fwSession);
  2369   if( CKR_OK != *pError ) {
  2370     return (NSSArena *)NULL;
  2372 #endif /* DEBUG */
  2374   return nssCKFWSession_GetArena(fwSession, pError);
  2377 /*
  2378  * NSSCKFWSession_CallNotification
  2380  */
  2382 NSS_IMPLEMENT CK_RV
  2383 NSSCKFWSession_CallNotification
  2385   NSSCKFWSession *fwSession,
  2386   CK_NOTIFICATION event
  2389 #ifdef DEBUG
  2390   CK_RV error = CKR_OK;
  2392   error = nssCKFWSession_verifyPointer(fwSession);
  2393   if( CKR_OK != error ) {
  2394     return error;
  2396 #endif /* DEBUG */
  2398   return nssCKFWSession_CallNotification(fwSession, event);
  2401 /*
  2402  * NSSCKFWSession_IsRWSession
  2404  */
  2406 NSS_IMPLEMENT CK_BBOOL
  2407 NSSCKFWSession_IsRWSession
  2409   NSSCKFWSession *fwSession
  2412 #ifdef DEBUG
  2413   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  2414     return CK_FALSE;
  2416 #endif /* DEBUG */
  2418   return nssCKFWSession_IsRWSession(fwSession);
  2421 /*
  2422  * NSSCKFWSession_IsSO
  2424  */
  2426 NSS_IMPLEMENT CK_BBOOL
  2427 NSSCKFWSession_IsSO
  2429   NSSCKFWSession *fwSession
  2432 #ifdef DEBUG
  2433   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  2434     return CK_FALSE;
  2436 #endif /* DEBUG */
  2438   return nssCKFWSession_IsSO(fwSession);
  2441 NSS_IMPLEMENT NSSCKFWCryptoOperation *
  2442 NSSCKFWSession_GetCurrentCryptoOperation
  2444   NSSCKFWSession *fwSession,
  2445   NSSCKFWCryptoOperationState state
  2448 #ifdef DEBUG
  2449   CK_RV error = CKR_OK;
  2450   error = nssCKFWSession_verifyPointer(fwSession);
  2451   if( CKR_OK != error ) {
  2452     return (NSSCKFWCryptoOperation *)NULL;
  2455   if ( state >= NSSCKFWCryptoOperationState_Max) {
  2456     return (NSSCKFWCryptoOperation *)NULL;
  2458 #endif /* DEBUG */
  2459   return nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);

mercurial