session.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:44k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /* 
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. #ifdef DEBUG
  34. static const char CVS_ID[] = "@(#) $RCSfile: session.c,v $ $Revision: 1.5 $ $Date: 2000/09/13 21:15:07 $ $Name: NSS_3_1_1_RTM $";
  35. #endif /* DEBUG */
  36. /*
  37.  * session.c
  38.  *
  39.  * This file implements the NSSCKFWSession type and methods.
  40.  */
  41. #ifndef CK_T
  42. #include "ck.h"
  43. #endif /* CK_T */
  44. /*
  45.  * NSSCKFWSession
  46.  *
  47.  *  -- create/destroy --
  48.  *  nssCKFWSession_Create
  49.  *  nssCKFWSession_Destroy
  50.  *
  51.  *  -- public accessors --
  52.  *  NSSCKFWSession_GetMDSession
  53.  *  NSSCKFWSession_GetArena
  54.  *  NSSCKFWSession_CallNotification
  55.  *  NSSCKFWSession_IsRWSession
  56.  *  NSSCKFWSession_IsSO
  57.  *
  58.  *  -- implement public accessors --
  59.  *  nssCKFWSession_GetMDSession
  60.  *  nssCKFWSession_GetArena
  61.  *  nssCKFWSession_CallNotification
  62.  *  nssCKFWSession_IsRWSession
  63.  *  nssCKFWSession_IsSO
  64.  *
  65.  *  -- private accessors --
  66.  *  nssCKFWSession_GetSlot
  67.  *  nssCKFWSession_GetSessionState
  68.  *  nssCKFWSession_SetFWFindObjects
  69.  *  nssCKFWSession_GetFWFindObjects
  70.  *  nssCKFWSession_SetMDSession
  71.  *  nssCKFWSession_SetHandle
  72.  *  nssCKFWSession_GetHandle
  73.  *  nssCKFWSession_RegisterSessionObject
  74.  *  nssCKFWSession_DeegisterSessionObject
  75.  *
  76.  *  -- module fronts --
  77.  *  nssCKFWSession_GetDeviceError
  78.  *  nssCKFWSession_Login
  79.  *  nssCKFWSession_Logout
  80.  *  nssCKFWSession_InitPIN
  81.  *  nssCKFWSession_SetPIN
  82.  *  nssCKFWSession_GetOperationStateLen
  83.  *  nssCKFWSession_GetOperationState
  84.  *  nssCKFWSession_SetOperationState
  85.  *  nssCKFWSession_CreateObject
  86.  *  nssCKFWSession_CopyObject
  87.  *  nssCKFWSession_FindObjectsInit
  88.  *  nssCKFWSession_SeedRandom
  89.  *  nssCKFWSession_GetRandom
  90.  */
  91. struct NSSCKFWSessionStr {
  92.   NSSArena *arena;
  93.   NSSCKMDSession *mdSession;
  94.   NSSCKFWToken *fwToken;
  95.   NSSCKMDToken *mdToken;
  96.   NSSCKFWInstance *fwInstance;
  97.   NSSCKMDInstance *mdInstance;
  98.   CK_VOID_PTR pApplication;
  99.   CK_NOTIFY Notify;
  100.   /*
  101.    * Everything above is set at creation time, and then not modified.
  102.    * The items below are atomic.  No locking required.  If we fear
  103.    * about pointer-copies being nonatomic, we'll lock fwFindObjects.
  104.    */
  105.   CK_BBOOL rw;
  106.   NSSCKFWFindObjects *fwFindObjects;
  107.   nssCKFWHash *sessionObjectHash;
  108.   CK_SESSION_HANDLE hSession;
  109. };
  110. #ifdef DEBUG
  111. /*
  112.  * But first, the pointer-tracking stuff.
  113.  *
  114.  * NOTE: the pointer-tracking support in NSS/base currently relies
  115.  * upon NSPR's CallOnce support.  That, however, relies upon NSPR's
  116.  * locking, which is tied into the runtime.  We need a pointer-tracker
  117.  * implementation that uses the locks supplied through C_Initialize.
  118.  * That support, however, can be filled in later.  So for now, I'll
  119.  * just do this routines as no-ops.
  120.  */
  121. static CK_RV
  122. session_add_pointer
  123. (
  124.   const NSSCKFWSession *fwSession
  125. )
  126. {
  127.   return CKR_OK;
  128. }
  129. static CK_RV
  130. session_remove_pointer
  131. (
  132.   const NSSCKFWSession *fwSession
  133. )
  134. {
  135.   return CKR_OK;
  136. }
  137. NSS_IMPLEMENT CK_RV
  138. nssCKFWSession_verifyPointer
  139. (
  140.   const NSSCKFWSession *fwSession
  141. )
  142. {
  143.   return CKR_OK;
  144. }
  145. #endif /* DEBUG */
  146. /*
  147.  * nssCKFWSession_Create
  148.  *
  149.  */
  150. NSS_IMPLEMENT NSSCKFWSession *
  151. nssCKFWSession_Create
  152. (
  153.   NSSCKFWToken *fwToken,
  154.   CK_BBOOL rw,
  155.   CK_VOID_PTR pApplication,
  156.   CK_NOTIFY Notify,
  157.   CK_RV *pError
  158. )
  159. {
  160.   NSSArena *arena = (NSSArena *)NULL;
  161.   NSSCKFWSession *fwSession;
  162.   NSSCKFWSlot *fwSlot;
  163. #ifdef NSSDEBUG
  164.   if( (CK_RV *)NULL == pError ) {
  165.     return (NSSCKFWSession *)NULL;
  166.   }
  167.   *pError = nssCKFWToken_verifyPointer(fwToken);
  168.   if( CKR_OK != *pError ) {
  169.     return (NSSCKFWSession *)NULL;
  170.   }
  171. #endif /* NSSDEBUG */
  172.   arena = NSSArena_Create();
  173.   if( (NSSArena *)NULL == arena ) {
  174.     *pError = CKR_HOST_MEMORY;
  175.     return (NSSCKFWSession *)NULL;
  176.   }
  177.   fwSession = nss_ZNEW(arena, NSSCKFWSession);
  178.   if( (NSSCKFWSession *)NULL == fwSession ) {
  179.     *pError = CKR_HOST_MEMORY;
  180.     goto loser;
  181.   }
  182.   fwSession->arena = arena;
  183.   fwSession->mdSession = (NSSCKMDSession *)NULL; /* set later */
  184.   fwSession->fwToken = fwToken;
  185.   fwSession->mdToken = nssCKFWToken_GetMDToken(fwToken);
  186.   fwSlot = nssCKFWToken_GetFWSlot(fwToken);
  187.   fwSession->fwInstance = nssCKFWSlot_GetFWInstance(fwSlot);
  188.   fwSession->mdInstance = nssCKFWSlot_GetMDInstance(fwSlot);
  189.   fwSession->rw = rw;
  190.   fwSession->pApplication = pApplication;
  191.   fwSession->Notify = Notify;
  192.   fwSession->fwFindObjects = (NSSCKFWFindObjects *)NULL;
  193.   fwSession->sessionObjectHash = nssCKFWHash_Create(fwSession->fwInstance, arena, pError);
  194.   if( (nssCKFWHash *)NULL == fwSession->sessionObjectHash ) {
  195.     if( CKR_OK == *pError ) {
  196.       *pError = CKR_GENERAL_ERROR;
  197.     }
  198.     goto loser;
  199.   }
  200. #ifdef DEBUG
  201.   *pError = session_add_pointer(fwSession);
  202.   if( CKR_OK != *pError ) {
  203.     goto loser;
  204.   }
  205. #endif /* DEBUG */
  206.   return fwSession;
  207.  loser:
  208.   if( (NSSArena *)NULL != arena ) {
  209.     if( (nssCKFWHash *)NULL != fwSession->sessionObjectHash ) {
  210.       (void)nssCKFWHash_Destroy(fwSession->sessionObjectHash);
  211.     }
  212.     NSSArena_Destroy(arena);
  213.   }
  214.   return (NSSCKFWSession *)NULL;
  215. }
  216. static void
  217. nss_ckfw_session_object_destroy_iterator
  218. (
  219.   const void *key,
  220.   void *value,
  221.   void *closure
  222. )
  223. {
  224.   NSSCKFWObject *fwObject = (NSSCKFWObject *)value;
  225.   nssCKFWObject_Finalize(fwObject);
  226. }
  227. /*
  228.  * nssCKFWSession_Destroy
  229.  *
  230.  */
  231. NSS_IMPLEMENT CK_RV
  232. nssCKFWSession_Destroy
  233. (
  234.   NSSCKFWSession *fwSession,
  235.   CK_BBOOL removeFromTokenHash
  236. )
  237. {
  238.   CK_RV error = CKR_OK;
  239.   nssCKFWHash *sessionObjectHash;
  240. #ifdef NSSDEBUG
  241.   error = nssCKFWSession_verifyPointer(fwSession);
  242.   if( CKR_OK != error ) {
  243.     return error;
  244.   }
  245. #endif /* NSSDEBUG */
  246.   if( removeFromTokenHash ) {
  247.     error = nssCKFWToken_RemoveSession(fwSession->fwToken, fwSession);
  248.   }
  249.   /*
  250.    * Invalidate session objects
  251.    */
  252.   sessionObjectHash = fwSession->sessionObjectHash;
  253.   fwSession->sessionObjectHash = (nssCKFWHash *)NULL;
  254.   nssCKFWHash_Iterate(sessionObjectHash, 
  255.                       nss_ckfw_session_object_destroy_iterator, 
  256.                       (void *)NULL);
  257. #ifdef DEBUG
  258.   (void)session_remove_pointer(fwSession);
  259. #endif /* DEBUG */
  260.   (void)nssCKFWHash_Destroy(sessionObjectHash);
  261.   NSSArena_Destroy(fwSession->arena);
  262.   return error;
  263. }
  264. /*
  265.  * nssCKFWSession_GetMDSession
  266.  *
  267.  */
  268. NSS_IMPLEMENT NSSCKMDSession *
  269. nssCKFWSession_GetMDSession
  270. (
  271.   NSSCKFWSession *fwSession
  272. )
  273. {
  274. #ifdef NSSDEBUG
  275.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  276.     return (NSSCKMDSession *)NULL;
  277.   }
  278. #endif /* NSSDEBUG */
  279.   return fwSession->mdSession;
  280. }
  281. /*
  282.  * nssCKFWSession_GetArena
  283.  *
  284.  */
  285. NSS_IMPLEMENT NSSArena *
  286. nssCKFWSession_GetArena
  287. (
  288.   NSSCKFWSession *fwSession,
  289.   CK_RV *pError
  290. )
  291. {
  292. #ifdef NSSDEBUG
  293.   if( (CK_RV *)NULL == pError ) {
  294.     return (NSSArena *)NULL;
  295.   }
  296.   *pError = nssCKFWSession_verifyPointer(fwSession);
  297.   if( CKR_OK != *pError ) {
  298.     return (NSSArena *)NULL;
  299.   }
  300. #endif /* NSSDEBUG */
  301.   return fwSession->arena;
  302. }
  303. /*
  304.  * nssCKFWSession_CallNotification
  305.  *
  306.  */
  307. NSS_IMPLEMENT CK_RV
  308. nssCKFWSession_CallNotification
  309. (
  310.   NSSCKFWSession *fwSession,
  311.   CK_NOTIFICATION event
  312. )
  313. {
  314.   CK_RV error = CKR_OK;
  315.   CK_SESSION_HANDLE handle;
  316. #ifdef NSSDEBUG
  317.   error = nssCKFWSession_verifyPointer(fwSession);
  318.   if( CKR_OK != error ) {
  319.     return error;
  320.   }
  321. #endif /* NSSDEBUG */
  322.   if( (CK_NOTIFY)NULL == fwSession->Notify ) {
  323.     return CKR_OK;
  324.   }
  325.   handle = nssCKFWInstance_FindSessionHandle(fwSession->fwInstance, fwSession);
  326.   if( (CK_SESSION_HANDLE)0 == handle ) {
  327.     return CKR_GENERAL_ERROR;
  328.   }
  329.   error = fwSession->Notify(handle, event, fwSession->pApplication);
  330.   return error;
  331. }
  332. /*
  333.  * nssCKFWSession_IsRWSession
  334.  *
  335.  */
  336. NSS_IMPLEMENT CK_BBOOL
  337. nssCKFWSession_IsRWSession
  338. (
  339.   NSSCKFWSession *fwSession
  340. )
  341. {
  342. #ifdef NSSDEBUG
  343.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  344.     return CK_FALSE;
  345.   }
  346. #endif /* NSSDEBUG */
  347.   return fwSession->rw;
  348. }
  349. /*
  350.  * nssCKFWSession_IsSO
  351.  *
  352.  */
  353. NSS_IMPLEMENT CK_BBOOL
  354. nssCKFWSession_IsSO
  355. (
  356.   NSSCKFWSession *fwSession
  357. )
  358. {
  359.   CK_STATE state;
  360. #ifdef NSSDEBUG
  361.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  362.     return CK_FALSE;
  363.   }
  364. #endif /* NSSDEBUG */
  365.   state = nssCKFWToken_GetSessionState(fwSession->fwToken);
  366.   switch( state ) {
  367.   case CKS_RO_PUBLIC_SESSION:
  368.   case CKS_RO_USER_FUNCTIONS:
  369.   case CKS_RW_PUBLIC_SESSION:
  370.   case CKS_RW_USER_FUNCTIONS:
  371.     return CK_FALSE;
  372.   case CKS_RW_SO_FUNCTIONS:
  373.     return CK_TRUE;
  374.   default:
  375.     return CK_FALSE;
  376.   }
  377. }
  378. /*
  379.  * nssCKFWSession_GetFWSlot
  380.  *
  381.  */
  382. NSS_IMPLEMENT NSSCKFWSlot *
  383. nssCKFWSession_GetFWSlot
  384. (
  385.   NSSCKFWSession *fwSession
  386. )
  387. {
  388. #ifdef NSSDEBUG
  389.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  390.     return (NSSCKFWSlot *)NULL;
  391.   }
  392. #endif /* NSSDEBUG */
  393.   return nssCKFWToken_GetFWSlot(fwSession->fwToken);
  394. }
  395. /*
  396.  * nssCFKWSession_GetSessionState
  397.  *
  398.  */
  399. NSS_IMPLEMENT CK_STATE
  400. nssCKFWSession_GetSessionState
  401. (
  402.   NSSCKFWSession *fwSession
  403. )
  404. {
  405. #ifdef NSSDEBUG
  406.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  407.     return CKS_RO_PUBLIC_SESSION; /* whatever */
  408.   }
  409. #endif /* NSSDEBUG */
  410.   return nssCKFWToken_GetSessionState(fwSession->fwToken);
  411. }
  412. /*
  413.  * nssCKFWSession_SetFWFindObjects
  414.  *
  415.  */
  416. NSS_IMPLEMENT CK_RV
  417. nssCKFWSession_SetFWFindObjects
  418. (
  419.   NSSCKFWSession *fwSession,
  420.   NSSCKFWFindObjects *fwFindObjects
  421. )
  422. {
  423. #ifdef NSSDEBUG
  424.   CK_RV error = CKR_OK;
  425. #endif /* NSSDEBUG */
  426. #ifdef NSSDEBUG
  427.   error = nssCKFWSession_verifyPointer(fwSession);
  428.   if( CKR_OK != error ) {
  429.     return error;
  430.   }
  431.   /* fwFindObjects may be null */
  432. #endif /* NSSDEBUG */
  433.   if( ((NSSCKFWFindObjects *)NULL != fwSession->fwFindObjects) &&
  434.       ((NSSCKFWFindObjects *)NULL != fwFindObjects) ) {
  435.     return CKR_OPERATION_ACTIVE;
  436.   }
  437.   fwSession->fwFindObjects = fwFindObjects;
  438.   return CKR_OK;
  439. }
  440. /*
  441.  * nssCKFWSession_GetFWFindObjects
  442.  *
  443.  */
  444. NSS_IMPLEMENT NSSCKFWFindObjects *
  445. nssCKFWSession_GetFWFindObjects
  446. (
  447.   NSSCKFWSession *fwSession,
  448.   CK_RV *pError
  449. )
  450. {
  451. #ifdef NSSDEBUG
  452.   if( (CK_RV *)NULL == pError ) {
  453.     return (NSSCKFWFindObjects *)NULL;
  454.   }
  455.   *pError = nssCKFWSession_verifyPointer(fwSession);
  456.   if( CKR_OK != *pError ) {
  457.     return (NSSCKFWFindObjects *)NULL;
  458.   }
  459. #endif /* NSSDEBUG */
  460.   if( (NSSCKFWFindObjects *)NULL == fwSession->fwFindObjects ) {
  461.     *pError = CKR_OPERATION_NOT_INITIALIZED;
  462.     return (NSSCKFWFindObjects *)NULL;
  463.   }
  464.   return fwSession->fwFindObjects;
  465. }
  466. /*
  467.  * nssCKFWSession_SetMDSession
  468.  *
  469.  */
  470. NSS_IMPLEMENT CK_RV
  471. nssCKFWSession_SetMDSession
  472. (
  473.   NSSCKFWSession *fwSession,
  474.   NSSCKMDSession *mdSession
  475. )
  476. {
  477. #ifdef NSSDEBUG
  478.   CK_RV error = CKR_OK;
  479. #endif /* NSSDEBUG */
  480. #ifdef NSSDEBUG
  481.   error = nssCKFWSession_verifyPointer(fwSession);
  482.   if( CKR_OK != error ) {
  483.     return error;
  484.   }
  485.   if( (NSSCKMDSession *)NULL == mdSession ) {
  486.     return CKR_ARGUMENTS_BAD;
  487.   }
  488. #endif /* NSSDEBUG */
  489.   if( (NSSCKMDSession *)NULL != fwSession->mdSession ) {
  490.     return CKR_GENERAL_ERROR;
  491.   }
  492.   fwSession->mdSession = mdSession;
  493.   return CKR_OK;
  494. }
  495. /*
  496.  * nssCKFWSession_SetHandle
  497.  *
  498.  */
  499. NSS_IMPLEMENT CK_RV
  500. nssCKFWSession_SetHandle
  501. (
  502.   NSSCKFWSession *fwSession,
  503.   CK_SESSION_HANDLE hSession
  504. )
  505. {
  506. #ifdef NSSDEBUG
  507.   CK_RV error = CKR_OK;
  508. #endif /* NSSDEBUG */
  509. #ifdef NSSDEBUG
  510.   error = nssCKFWSession_verifyPointer(fwSession);
  511.   if( CKR_OK != error ) {
  512.     return error;
  513.   }
  514. #endif /* NSSDEBUG */
  515.   if( (CK_SESSION_HANDLE)0 != fwSession->hSession ) {
  516.     return CKR_GENERAL_ERROR;
  517.   }
  518.   fwSession->hSession = hSession;
  519.   return CKR_OK;
  520. }
  521. /*
  522.  * nssCKFWSession_GetHandle
  523.  *
  524.  */
  525. NSS_IMPLEMENT CK_SESSION_HANDLE
  526. nssCKFWSession_GetHandle
  527. (
  528.   NSSCKFWSession *fwSession
  529. )
  530. {
  531. #ifdef NSSDEBUG
  532.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  533.     return NULL;
  534.   }
  535. #endif /* NSSDEBUG */
  536.   return fwSession->hSession;
  537. }
  538. /*
  539.  * nssCKFWSession_RegisterSessionObject
  540.  *
  541.  */
  542. NSS_IMPLEMENT CK_RV
  543. nssCKFWSession_RegisterSessionObject
  544. (
  545.   NSSCKFWSession *fwSession,
  546.   NSSCKFWObject *fwObject
  547. )
  548. {
  549.   CK_RV rv = CKR_OK;
  550. #ifdef NSSDEBUG
  551.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  552.     return CKR_GENERAL_ERROR;
  553.   }
  554. #endif /* NSSDEBUG */
  555.   if( (nssCKFWHash *)NULL != fwSession->sessionObjectHash ) {
  556.     rv = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject);
  557.   }
  558.   return rv;
  559. }
  560. /*
  561.  * nssCKFWSession_DeregisterSessionObject
  562.  *
  563.  */
  564. NSS_IMPLEMENT CK_RV
  565. nssCKFWSession_DeregisterSessionObject
  566. (
  567.   NSSCKFWSession *fwSession,
  568.   NSSCKFWObject *fwObject
  569. )
  570. {
  571. #ifdef NSSDEBUG
  572.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  573.     return CKR_GENERAL_ERROR;
  574.   }
  575. #endif /* NSSDEBUG */
  576.   if( (nssCKFWHash *)NULL != fwSession->sessionObjectHash ) {
  577.     nssCKFWHash_Remove(fwSession->sessionObjectHash, fwObject);
  578.   }
  579.   return CKR_OK;
  580. }
  581. /*
  582.  * nssCKFWSession_GetDeviceError
  583.  *
  584.  */
  585. NSS_IMPLEMENT CK_ULONG
  586. nssCKFWSession_GetDeviceError
  587. (
  588.   NSSCKFWSession *fwSession
  589. )
  590. {
  591. #ifdef NSSDEBUG
  592.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  593.     return (CK_ULONG)0;
  594.   }
  595.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  596.     return (CK_ULONG)0;
  597.   }
  598. #endif /* NSSDEBUG */
  599.   if( (void *)NULL == (void *)fwSession->mdSession->GetDeviceError ) {
  600.     return (CK_ULONG)0;
  601.   }
  602.   return fwSession->mdSession->GetDeviceError(fwSession->mdSession, 
  603.     fwSession, fwSession->mdToken, fwSession->fwToken, 
  604.     fwSession->mdInstance, fwSession->fwInstance);
  605. }
  606. /*
  607.  * nssCKFWSession_Login
  608.  *
  609.  */
  610. NSS_IMPLEMENT CK_RV
  611. nssCKFWSession_Login
  612. (
  613.   NSSCKFWSession *fwSession,
  614.   CK_USER_TYPE userType,
  615.   NSSItem *pin
  616. )
  617. {
  618.   CK_RV error = CKR_OK;
  619.   CK_STATE oldState;
  620.   CK_STATE newState;
  621. #ifdef NSSDEBUG
  622.   error = nssCKFWSession_verifyPointer(fwSession);
  623.   if( CKR_OK != error ) {
  624.     return error;
  625.   }
  626.   switch( userType ) {
  627.   case CKU_SO:
  628.   case CKU_USER:
  629.     break;
  630.   default:
  631.     return CKR_USER_TYPE_INVALID;
  632.   }
  633.   if( (NSSItem *)NULL == pin ) {
  634.     if( CK_TRUE != nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken) ) {
  635.       return CKR_ARGUMENTS_BAD;
  636.     }
  637.   }
  638.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  639.     return CKR_GENERAL_ERROR;
  640.   }
  641. #endif /* NSSDEBUG */
  642.   oldState = nssCKFWToken_GetSessionState(fwSession->fwToken);
  643.   /*
  644.    * It's not clear what happens when you're already logged in.
  645.    * I'll just fail; but if we decide to change, the logic is
  646.    * all right here.
  647.    */
  648.   if( CKU_SO == userType ) {
  649.     switch( oldState ) {
  650.     case CKS_RO_PUBLIC_SESSION:      
  651.       /*
  652.        * There's no such thing as a read-only security officer
  653.        * session, so fail.  The error should be CKR_SESSION_READ_ONLY,
  654.        * except that C_Login isn't defined to return that.  So we'll
  655.        * do CKR_SESSION_READ_ONLY_EXISTS, which is what is documented.
  656.        */
  657.       return CKR_SESSION_READ_ONLY_EXISTS;
  658.     case CKS_RO_USER_FUNCTIONS:
  659.       return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
  660.     case CKS_RW_PUBLIC_SESSION:
  661.       newState = CKS_RW_SO_FUNCTIONS;
  662.       break;
  663.     case CKS_RW_USER_FUNCTIONS:
  664.       return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
  665.     case CKS_RW_SO_FUNCTIONS:
  666.       return CKR_USER_ALREADY_LOGGED_IN;
  667.     default:
  668.       return CKR_GENERAL_ERROR;
  669.     }
  670.   } else /* CKU_USER == userType */ {
  671.     switch( oldState ) {
  672.     case CKS_RO_PUBLIC_SESSION:      
  673.       newState = CKS_RO_USER_FUNCTIONS;
  674.       break;
  675.     case CKS_RO_USER_FUNCTIONS:
  676.       return CKR_USER_ALREADY_LOGGED_IN;
  677.     case CKS_RW_PUBLIC_SESSION:
  678.       newState = CKS_RW_USER_FUNCTIONS;
  679.       break;
  680.     case CKS_RW_USER_FUNCTIONS:
  681.       return CKR_USER_ALREADY_LOGGED_IN;
  682.     case CKS_RW_SO_FUNCTIONS:
  683.       return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
  684.     default:
  685.       return CKR_GENERAL_ERROR;
  686.     }
  687.   }
  688.   /*
  689.    * So now we're in one of three cases:
  690.    *
  691.    * Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_SO_FUNCTIONS;
  692.    * Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_USER_FUNCTIONS;
  693.    * Old == CKS_RO_PUBLIC_SESSION, New == CKS_RO_USER_FUNCTIONS;
  694.    */
  695.   if( (void *)NULL == (void *)fwSession->mdSession->Login ) {
  696.     /*
  697.      * The Module doesn't want to be informed (or check the pin)
  698.      * it'll just rely on the Framework as needed.
  699.      */
  700.     ;
  701.   } else {
  702.     error = fwSession->mdSession->Login(fwSession->mdSession, fwSession,
  703.       fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  704.       fwSession->fwInstance, userType, pin, oldState, newState);
  705.     if( CKR_OK != error ) {
  706.       return error;
  707.     }
  708.   }
  709.   (void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState);
  710.   return CKR_OK;
  711. }
  712. /*
  713.  * nssCKFWSession_Logout
  714.  *
  715.  */
  716. NSS_IMPLEMENT CK_RV
  717. nssCKFWSession_Logout
  718. (
  719.   NSSCKFWSession *fwSession
  720. )
  721. {
  722.   CK_RV error = CKR_OK;
  723.   CK_STATE oldState;
  724.   CK_STATE newState;
  725. #ifdef NSSDEBUG
  726.   error = nssCKFWSession_verifyPointer(fwSession);
  727.   if( CKR_OK != error ) {
  728.     return error;
  729.   }
  730.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  731.     return CKR_GENERAL_ERROR;
  732.   }
  733. #endif /* NSSDEBUG */
  734.   oldState = nssCKFWToken_GetSessionState(fwSession->fwToken);
  735.   switch( oldState ) {
  736.   case CKS_RO_PUBLIC_SESSION:
  737.     return CKR_USER_NOT_LOGGED_IN;
  738.   case CKS_RO_USER_FUNCTIONS:
  739.     newState = CKS_RO_PUBLIC_SESSION;
  740.     break;
  741.   case CKS_RW_PUBLIC_SESSION:
  742.     return CKR_USER_NOT_LOGGED_IN;
  743.   case CKS_RW_USER_FUNCTIONS:
  744.     newState = CKS_RW_PUBLIC_SESSION;
  745.     break;
  746.   case CKS_RW_SO_FUNCTIONS:
  747.     newState = CKS_RW_PUBLIC_SESSION;
  748.     break;
  749.   default:
  750.     return CKR_GENERAL_ERROR;
  751.   }
  752.   /*
  753.    * So now we're in one of three cases:
  754.    *
  755.    * Old == CKS_RW_SO_FUNCTIONS,   New == CKS_RW_PUBLIC_SESSION;
  756.    * Old == CKS_RW_USER_FUNCTIONS, New == CKS_RW_PUBLIC_SESSION;
  757.    * Old == CKS_RO_USER_FUNCTIONS, New == CKS_RO_PUBLIC_SESSION;
  758.    */
  759.   if( (void *)NULL == (void *)fwSession->mdSession->Logout ) {
  760.     /*
  761.      * The Module doesn't want to be informed.  Okay.
  762.      */
  763.     ;
  764.   } else {
  765.     error = fwSession->mdSession->Logout(fwSession->mdSession, fwSession,
  766.       fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  767.       fwSession->fwInstance, oldState, newState);
  768.     if( CKR_OK != error ) {
  769.       /*
  770.        * Now what?!  A failure really should end up with the Framework
  771.        * considering it logged out, right?
  772.        */
  773.       ;
  774.     }
  775.   }
  776.   (void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState);
  777.   return error;
  778. }
  779. /*
  780.  * nssCKFWSession_InitPIN
  781.  *
  782.  */
  783. NSS_IMPLEMENT CK_RV
  784. nssCKFWSession_InitPIN
  785. (
  786.   NSSCKFWSession *fwSession,
  787.   NSSItem *pin
  788. )
  789. {
  790.   CK_RV error = CKR_OK;
  791.   CK_STATE state;
  792. #ifdef NSSDEBUG
  793.   error = nssCKFWSession_verifyPointer(fwSession);
  794.   if( CKR_OK != error ) {
  795.     return error;
  796.   }
  797.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  798.     return CKR_GENERAL_ERROR;
  799.   }
  800. #endif /* NSSDEBUG */
  801.   state = nssCKFWToken_GetSessionState(fwSession->fwToken);
  802.   if( CKS_RW_SO_FUNCTIONS != state ) {
  803.     return CKR_USER_NOT_LOGGED_IN;
  804.   }
  805.   if( (NSSItem *)NULL == pin ) {
  806.     CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
  807.     if( CK_TRUE != has ) {
  808.       return CKR_ARGUMENTS_BAD;
  809.     }
  810.   }
  811.   if( (void *)NULL == (void *)fwSession->mdSession->InitPIN ) {
  812.     return CKR_TOKEN_WRITE_PROTECTED;
  813.   }
  814.   error = fwSession->mdSession->InitPIN(fwSession->mdSession, fwSession,
  815.     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  816.     fwSession->fwInstance, pin);
  817.   return error;
  818. }
  819. /*
  820.  * nssCKFWSession_SetPIN
  821.  *
  822.  */
  823. NSS_IMPLEMENT CK_RV
  824. nssCKFWSession_SetPIN
  825. (
  826.   NSSCKFWSession *fwSession,
  827.   NSSItem *newPin,
  828.   NSSItem *oldPin
  829. )
  830. {
  831.   CK_RV error = CKR_OK;
  832.   CK_STATE state;
  833. #ifdef NSSDEBUG
  834.   error = nssCKFWSession_verifyPointer(fwSession);
  835.   if( CKR_OK != error ) {
  836.     return error;
  837.   }
  838.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  839.     return CKR_GENERAL_ERROR;
  840.   }
  841. #endif /* NSSDEBUG */
  842.   state = nssCKFWToken_GetSessionState(fwSession->fwToken);
  843.   if( (CKS_RW_SO_FUNCTIONS != state) &&
  844.       (CKS_RW_USER_FUNCTIONS != state) ) {
  845.     return CKR_USER_NOT_LOGGED_IN;
  846.   }
  847.   if( (NSSItem *)NULL == newPin ) {
  848.     CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
  849.     if( CK_TRUE != has ) {
  850.       return CKR_ARGUMENTS_BAD;
  851.     }
  852.   }
  853.   if( (NSSItem *)NULL == oldPin ) {
  854.     CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
  855.     if( CK_TRUE != has ) {
  856.       return CKR_ARGUMENTS_BAD;
  857.     }
  858.   }
  859.   if( (void *)NULL == (void *)fwSession->mdSession->SetPIN ) {
  860.     return CKR_TOKEN_WRITE_PROTECTED;
  861.   }
  862.   error = fwSession->mdSession->SetPIN(fwSession->mdSession, fwSession,
  863.     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  864.     fwSession->fwInstance, newPin, oldPin);
  865.   return error;
  866. }
  867. /*
  868.  * nssCKFWSession_GetOperationStateLen
  869.  *
  870.  */
  871. NSS_IMPLEMENT CK_ULONG
  872. nssCKFWSession_GetOperationStateLen
  873. (
  874.   NSSCKFWSession *fwSession,
  875.   CK_RV *pError
  876. )
  877. {
  878.   CK_ULONG mdAmt;
  879.   CK_ULONG fwAmt;
  880. #ifdef NSSDEBUG
  881.   if( (CK_RV *)NULL == pError ) {
  882.     return (CK_ULONG)0;
  883.   }
  884.   *pError = nssCKFWSession_verifyPointer(fwSession);
  885.   if( CKR_OK != *pError ) {
  886.     return (CK_ULONG)0;
  887.   }
  888.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  889.     *pError = CKR_GENERAL_ERROR;
  890.     return (CK_ULONG)0;
  891.   }
  892. #endif /* NSSDEBUG */
  893.   if( (void *)NULL == (void *)fwSession->mdSession->GetOperationStateLen ) {
  894.     *pError = CKR_STATE_UNSAVEABLE;
  895.   }
  896.   /*
  897.    * We could check that the session is actually in some state..
  898.    */
  899.   mdAmt = fwSession->mdSession->GetOperationStateLen(fwSession->mdSession,
  900.     fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  901.     fwSession->fwInstance, pError);
  902.   if( ((CK_ULONG)0 == mdAmt) && (CKR_OK != *pError) ) {
  903.     return (CK_ULONG)0;
  904.   }
  905.   /*
  906.    * Add a bit of sanity-checking
  907.    */
  908.   fwAmt = mdAmt + 2*sizeof(CK_ULONG);
  909.   return fwAmt;
  910. }
  911. /*
  912.  * nssCKFWSession_GetOperationState
  913.  *
  914.  */
  915. NSS_IMPLEMENT CK_RV
  916. nssCKFWSession_GetOperationState
  917. (
  918.   NSSCKFWSession *fwSession,
  919.   NSSItem *buffer
  920. )
  921. {
  922.   CK_RV error = CKR_OK;
  923.   CK_ULONG fwAmt;
  924.   CK_ULONG *ulBuffer;
  925.   NSSItem i2;
  926.   CK_ULONG n, i;
  927. #ifdef NSSDEBUG
  928.   error = nssCKFWSession_verifyPointer(fwSession);
  929.   if( CKR_OK != error ) {
  930.     return error;
  931.   }
  932.   if( (NSSItem *)NULL == buffer ) {
  933.     return CKR_ARGUMENTS_BAD;
  934.   }
  935.   if( (void *)NULL == buffer->data ) {
  936.     return CKR_ARGUMENTS_BAD;
  937.   }
  938.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  939.     return CKR_GENERAL_ERROR;
  940.   }
  941. #endif /* NSSDEBUG */
  942.   if( (void *)NULL == (void *)fwSession->mdSession->GetOperationState ) {
  943.     return CKR_STATE_UNSAVEABLE;
  944.   }
  945.   /*
  946.    * Sanity-check the caller's buffer.
  947.    */
  948.   error = CKR_OK;
  949.   fwAmt = nssCKFWSession_GetOperationStateLen(fwSession, &error);
  950.   if( ((CK_ULONG)0 == fwAmt) && (CKR_OK != error) ) {
  951.     return error;
  952.   }
  953.   if( buffer->size < fwAmt ) {
  954.     return CKR_BUFFER_TOO_SMALL;
  955.   }
  956.   ulBuffer = (CK_ULONG *)buffer->data;
  957.   i2.size = buffer->size - 2*sizeof(CK_ULONG);
  958.   i2.data = (void *)&ulBuffer[2];
  959.   error = fwSession->mdSession->GetOperationState(fwSession->mdSession,
  960.     fwSession, fwSession->mdToken, fwSession->fwToken, 
  961.     fwSession->mdInstance, fwSession->fwInstance, &i2);
  962.   if( CKR_OK != error ) {
  963.     return error;
  964.   }
  965.   /*
  966.    * Add a little integrety/identity check.  
  967.    * NOTE: right now, it's pretty stupid.  
  968.    * A CRC or something would be better.
  969.    */
  970.   ulBuffer[0] = 0x434b4657; /* CKFW */
  971.   ulBuffer[1] = 0;
  972.   n = i2.size/sizeof(CK_ULONG);
  973.   for( i = 0; i < n; i++ ) {
  974.     ulBuffer[1] ^= ulBuffer[2+i];
  975.   }
  976.   return CKR_OK;
  977. }
  978. /*
  979.  * nssCKFWSession_SetOperationState
  980.  *
  981.  */
  982. NSS_IMPLEMENT CK_RV
  983. nssCKFWSession_SetOperationState
  984. (
  985.   NSSCKFWSession *fwSession,
  986.   NSSItem *state,
  987.   NSSCKFWObject *encryptionKey,
  988.   NSSCKFWObject *authenticationKey
  989. )
  990. {
  991.   CK_RV error = CKR_OK;
  992.   CK_ULONG *ulBuffer;
  993.   CK_ULONG n, i;
  994.   CK_ULONG x;
  995.   NSSItem s;
  996.   NSSCKMDObject *mdek;
  997.   NSSCKMDObject *mdak;
  998. #ifdef NSSDEBUG
  999.   error = nssCKFWSession_verifyPointer(fwSession);
  1000.   if( CKR_OK != error ) {
  1001.     return error;
  1002.   }
  1003.   if( (NSSItem *)NULL == state ) {
  1004.     return CKR_ARGUMENTS_BAD;
  1005.   }
  1006.   if( (void *)NULL == state->data ) {
  1007.     return CKR_ARGUMENTS_BAD;
  1008.   }
  1009.   if( (NSSCKFWObject *)NULL != encryptionKey ) {
  1010.     error = nssCKFWObject_verifyPointer(encryptionKey);
  1011.     if( CKR_OK != error ) {
  1012.       return error;
  1013.     }
  1014.   }
  1015.   if( (NSSCKFWObject *)NULL != authenticationKey ) {
  1016.     error = nssCKFWObject_verifyPointer(authenticationKey);
  1017.     if( CKR_OK != error ) {
  1018.       return error;
  1019.     }
  1020.   }
  1021.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  1022.     return CKR_GENERAL_ERROR;
  1023.   }
  1024. #endif /* NSSDEBUG */
  1025.   ulBuffer = (CK_ULONG *)state->data;
  1026.   if( 0x43b4657 != ulBuffer[0] ) {
  1027.     return CKR_SAVED_STATE_INVALID;
  1028.   }
  1029.   n = (state->size / sizeof(CK_ULONG)) - 2;
  1030.   x = (CK_ULONG)0;
  1031.   for( i = 0; i < n; i++ ) {
  1032.     x ^= ulBuffer[2+i];
  1033.   }
  1034.   if( x != ulBuffer[1] ) {
  1035.     return CKR_SAVED_STATE_INVALID;
  1036.   }
  1037.   if( (void *)NULL == (void *)fwSession->mdSession->SetOperationState ) {
  1038.     return CKR_GENERAL_ERROR;
  1039.   }
  1040.   s.size = state->size - 2*sizeof(CK_ULONG);
  1041.   s.data = (void *)&ulBuffer[2];
  1042.   if( (NSSCKFWObject *)NULL != encryptionKey ) {
  1043.     mdek = nssCKFWObject_GetMDObject(encryptionKey);
  1044.   } else {
  1045.     mdek = (NSSCKMDObject *)NULL;
  1046.   }
  1047.   if( (NSSCKFWObject *)NULL != authenticationKey ) {
  1048.     mdak = nssCKFWObject_GetMDObject(authenticationKey);
  1049.   } else {
  1050.     mdak = (NSSCKMDObject *)NULL;
  1051.   }
  1052.   error = fwSession->mdSession->SetOperationState(fwSession->mdSession, 
  1053.     fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  1054.     fwSession->fwInstance, &s, mdek, encryptionKey, mdak, authenticationKey);
  1055.   if( CKR_OK != error ) {
  1056.     return error;
  1057.   }
  1058.   /*
  1059.    * Here'd we restore any session data
  1060.    */
  1061.   
  1062.   return CKR_OK;
  1063. }
  1064. static CK_BBOOL
  1065. nss_attributes_form_token_object
  1066. (
  1067.   CK_ATTRIBUTE_PTR pTemplate,
  1068.   CK_ULONG ulAttributeCount
  1069. )
  1070. {
  1071.   CK_ULONG i;
  1072.   CK_BBOOL rv;
  1073.   for( i = 0; i < ulAttributeCount; i++ ) {
  1074.     if( CKA_TOKEN == pTemplate[i].type ) {
  1075.       /* If we sanity-check, we can remove this sizeof check */
  1076.       if( sizeof(CK_BBOOL) == pTemplate[i].ulValueLen ) {
  1077.         (void)nsslibc_memcpy(&rv, pTemplate[i].pValue, sizeof(CK_BBOOL));
  1078.         return rv;
  1079.       } else {
  1080.         return CK_FALSE;
  1081.       }
  1082.     }
  1083.   }
  1084.   return CK_FALSE;
  1085. }
  1086. /*
  1087.  * nssCKFWSession_CreateObject
  1088.  *
  1089.  */
  1090. NSS_IMPLEMENT NSSCKFWObject *
  1091. nssCKFWSession_CreateObject
  1092. (
  1093.   NSSCKFWSession *fwSession,
  1094.   CK_ATTRIBUTE_PTR pTemplate,
  1095.   CK_ULONG ulAttributeCount,
  1096.   CK_RV *pError
  1097. )
  1098. {
  1099.   NSSArena *arena;
  1100.   NSSCKMDObject *mdObject;
  1101.   NSSCKFWObject *fwObject;
  1102.   CK_BBOOL isTokenObject;
  1103. #ifdef NSSDEBUG
  1104.   if( (CK_RV *)NULL == pError ) {
  1105.     return (NSSCKFWObject *)NULL;
  1106.   }
  1107.   *pError = nssCKFWSession_verifyPointer(fwSession);
  1108.   if( CKR_OK != pError ) {
  1109.     return (NSSCKFWObject *)NULL;
  1110.   }
  1111.   if( (CK_ATTRIBUTE_PTR)NULL == pTemplate ) {
  1112.     *pError = CKR_ARGUMENTS_BAD;
  1113.     return (NSSCKFWObject *)NULL;
  1114.   }
  1115.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  1116.     *pError = CKR_GENERAL_ERROR;
  1117.     return (NSSCKFWObject *)NULL;
  1118.   }
  1119. #endif /* NSSDEBUG */
  1120.   /*
  1121.    * Here would be an excellent place to sanity-check the object.
  1122.    */
  1123.   isTokenObject = nss_attributes_form_token_object(pTemplate, ulAttributeCount);
  1124.   if( CK_TRUE == isTokenObject ) {
  1125.     /* === TOKEN OBJECT === */
  1126.     if( (void *)NULL == (void *)fwSession->mdSession->CreateObject ) {
  1127.       *pError = CKR_TOKEN_WRITE_PROTECTED;
  1128.       return (NSSCKFWObject *)NULL;
  1129.     }
  1130.     arena = nssCKFWToken_GetArena(fwSession->fwToken, pError);
  1131.     if( (NSSArena *)NULL == arena ) {
  1132.       if( CKR_OK == *pError ) {
  1133.         *pError = CKR_GENERAL_ERROR;
  1134.       }
  1135.       return (NSSCKFWObject *)NULL;
  1136.     }
  1137.     goto callmdcreateobject;
  1138.   } else {
  1139.     /* === SESSION OBJECT === */
  1140.     arena = nssCKFWSession_GetArena(fwSession, pError);
  1141.     if( (NSSArena *)NULL == arena ) {
  1142.       if( CKR_OK == *pError ) {
  1143.         *pError = CKR_GENERAL_ERROR;
  1144.       }
  1145.       return (NSSCKFWObject *)NULL;
  1146.     }
  1147.     if( CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects(
  1148.                      fwSession->fwInstance) ) {
  1149.       /* --- module handles the session object -- */
  1150.       if( (void *)NULL == (void *)fwSession->mdSession->CreateObject ) {
  1151.         *pError = CKR_GENERAL_ERROR;
  1152.         return (NSSCKFWObject *)NULL;
  1153.       }
  1154.       
  1155.       goto callmdcreateobject;
  1156.     } else {
  1157.       /* --- framework handles the session object -- */
  1158.       mdObject = nssCKMDSessionObject_Create(fwSession->fwToken, 
  1159.         arena, pTemplate, ulAttributeCount, pError);
  1160.       goto gotmdobject;
  1161.     }
  1162.   }
  1163.  callmdcreateobject:
  1164.   mdObject = fwSession->mdSession->CreateObject(fwSession->mdSession,
  1165.     fwSession, fwSession->mdToken, fwSession->fwToken,
  1166.     fwSession->mdInstance, fwSession->fwInstance, arena, pTemplate,
  1167.     ulAttributeCount, pError);
  1168.  gotmdobject:
  1169.   if( (NSSCKMDObject *)NULL == mdObject ) {
  1170.     if( CKR_OK == *pError ) {
  1171.       *pError = CKR_GENERAL_ERROR;
  1172.     }
  1173.     return (NSSCKFWObject *)NULL;
  1174.   }
  1175.   fwObject = nssCKFWObject_Create(arena, mdObject, fwSession, 
  1176.     fwSession->fwToken, fwSession->fwInstance, pError);
  1177.   if( (NSSCKFWObject *)NULL == fwObject ) {
  1178.     if( CKR_OK == *pError ) {
  1179.       *pError = CKR_GENERAL_ERROR;
  1180.     }
  1181.     
  1182.     if( (void *)NULL != (void *)mdObject->Destroy ) {
  1183.       (void)mdObject->Destroy(mdObject, (NSSCKFWObject *)NULL,
  1184.         fwSession->mdSession, fwSession, fwSession->mdToken,
  1185.         fwSession->fwToken, fwSession->mdInstance, fwSession->fwInstance);
  1186.     }
  1187.     
  1188.     return (NSSCKFWObject *)NULL;
  1189.   }
  1190.   if( CK_FALSE == isTokenObject ) {
  1191.     if( CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, fwObject) ) {
  1192.       *pError = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject);
  1193.       if( CKR_OK != *pError ) {
  1194.         nssCKFWObject_Finalize(fwObject);
  1195.         return (NSSCKFWObject *)NULL;
  1196.       }
  1197.     }
  1198.   }
  1199.   
  1200.   return fwObject;
  1201. }
  1202. /*
  1203.  * nssCKFWSession_CopyObject
  1204.  *
  1205.  */
  1206. NSS_IMPLEMENT NSSCKFWObject *
  1207. nssCKFWSession_CopyObject
  1208. (
  1209.   NSSCKFWSession *fwSession,
  1210.   NSSCKFWObject *fwObject,
  1211.   CK_ATTRIBUTE_PTR pTemplate,
  1212.   CK_ULONG ulAttributeCount,
  1213.   CK_RV *pError
  1214. )
  1215. {
  1216.   CK_BBOOL oldIsToken;
  1217.   CK_BBOOL newIsToken;
  1218.   CK_ULONG i;
  1219.   NSSCKFWObject *rv;
  1220. #ifdef NSSDEBUG
  1221.   if( (CK_RV *)NULL == pError ) {
  1222.     return (NSSCKFWObject *)NULL;
  1223.   }
  1224.   *pError = nssCKFWSession_verifyPointer(fwSession);
  1225.   if( CKR_OK != *pError ) {
  1226.     return (NSSCKFWObject *)NULL;
  1227.   }
  1228.   *pError = nssCKFWObject_verifyPointer(fwObject);
  1229.   if( CKR_OK != *pError ) {
  1230.     return (NSSCKFWObject *)NULL;
  1231.   }
  1232.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  1233.     *pError = CKR_GENERAL_ERROR;
  1234.     return (NSSCKFWObject *)NULL;
  1235.   }
  1236. #endif /* NSSDEBUG */
  1237.   /*
  1238.    * Sanity-check object
  1239.    */
  1240.   oldIsToken = nssCKFWObject_IsTokenObject(fwObject);
  1241.   newIsToken = oldIsToken;
  1242.   for( i = 0; i < ulAttributeCount; i++ ) {
  1243.     if( CKA_TOKEN == pTemplate[i].type ) {
  1244.       /* Since we sanity-checked the object, we know this is the right size. */
  1245.       (void)nsslibc_memcpy(&newIsToken, pTemplate[i].pValue, sizeof(CK_BBOOL));
  1246.       break;
  1247.     }
  1248.   }
  1249.   /*
  1250.    * If the Module handles its session objects, or if both the new
  1251.    * and old object are token objects, use CopyObject if it exists.
  1252.    */
  1253.   if( ((void *)NULL != (void *)fwSession->mdSession->CopyObject) &&
  1254.       (((CK_TRUE == oldIsToken) && (CK_TRUE == newIsToken)) ||
  1255.        (CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects(
  1256.                      fwSession->fwInstance))) ) {
  1257.     /* use copy object */
  1258.     NSSArena *arena;
  1259.     NSSCKMDObject *mdOldObject;
  1260.     NSSCKMDObject *mdObject;
  1261.     mdOldObject = nssCKFWObject_GetMDObject(fwObject);
  1262.     if( CK_TRUE == newIsToken ) {
  1263.       arena = nssCKFWToken_GetArena(fwSession->fwToken, pError);
  1264.     } else {
  1265.       arena = nssCKFWSession_GetArena(fwSession, pError);
  1266.     }
  1267.     if( (NSSArena *)NULL == arena ) {
  1268.       if( CKR_OK == *pError ) {
  1269.         *pError = CKR_GENERAL_ERROR;
  1270.       }
  1271.       return (NSSCKFWObject *)NULL;
  1272.     }
  1273.     mdObject = fwSession->mdSession->CopyObject(fwSession->mdSession,
  1274.       fwSession, fwSession->mdToken, fwSession->fwToken,
  1275.       fwSession->mdInstance, fwSession->fwInstance, mdOldObject,
  1276.       fwObject, arena, pTemplate, ulAttributeCount, pError);
  1277.     if( (NSSCKMDObject *)NULL == mdObject ) {
  1278.       if( CKR_OK == *pError ) {
  1279.         *pError = CKR_GENERAL_ERROR;
  1280.       }
  1281.       return (NSSCKFWObject *)NULL;
  1282.     }
  1283.     rv = nssCKFWObject_Create(arena, mdObject, fwSession,
  1284.       fwSession->fwToken, fwSession->fwInstance, pError);
  1285.     if( (NSSCKFWObject *)NULL == fwObject ) {
  1286.       if( CKR_OK == *pError ) {
  1287.         *pError = CKR_GENERAL_ERROR;
  1288.       }
  1289.       if( (void *)NULL != (void *)mdObject->Destroy ) {
  1290.         (void)mdObject->Destroy(mdObject, (NSSCKFWObject *)NULL,
  1291.           fwSession->mdSession, fwSession, fwSession->mdToken,
  1292.           fwSession->fwToken, fwSession->mdInstance, fwSession->fwInstance);
  1293.       }
  1294.     
  1295.       return (NSSCKFWObject *)NULL;
  1296.     }
  1297.     if( CK_FALSE == newIsToken ) {
  1298.       if( CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, rv) ) {
  1299.         *pError = nssCKFWHash_Add(fwSession->sessionObjectHash, rv, rv);
  1300.         if( CKR_OK != *pError ) {
  1301.           nssCKFWObject_Finalize(rv);
  1302.           return (NSSCKFWObject *)NULL;
  1303.         }
  1304.       }
  1305.     }
  1306.     return rv;
  1307.   } else {
  1308.     /* use create object */
  1309.     NSSArena *tmpArena;
  1310.     CK_ATTRIBUTE_PTR newTemplate;
  1311.     CK_ULONG i, j, n, newLength, k;
  1312.     CK_ATTRIBUTE_TYPE_PTR oldTypes;
  1313.     NSSCKFWObject *rv;
  1314.     
  1315.     tmpArena = NSSArena_Create();
  1316.     if( (NSSArena *)NULL == tmpArena ) {
  1317.       *pError = CKR_HOST_MEMORY;
  1318.       return (NSSCKFWObject *)NULL;
  1319.     }
  1320.     n = nssCKFWObject_GetAttributeCount(fwObject, pError);
  1321.     if( (0 == n) && (CKR_OK != *pError) ) {
  1322.       return (NSSCKFWObject *)NULL;
  1323.     }
  1324.     oldTypes = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE_TYPE, n);
  1325.     if( (CK_ATTRIBUTE_TYPE_PTR)NULL == oldTypes ) {
  1326.       NSSArena_Destroy(tmpArena);
  1327.       *pError = CKR_HOST_MEMORY;
  1328.       return (NSSCKFWObject *)NULL;
  1329.     }
  1330.     *pError = nssCKFWObject_GetAttributeTypes(fwObject, oldTypes, n);
  1331.     if( CKR_OK != *pError ) {
  1332.       NSSArena_Destroy(tmpArena);
  1333.       return (NSSCKFWObject *)NULL;
  1334.     }
  1335.     newLength = n;
  1336.     for( i = 0; i < ulAttributeCount; i++ ) {
  1337.       for( j = 0; j < n; j++ ) {
  1338.         if( oldTypes[j] == pTemplate[i].type ) {
  1339.           if( (CK_VOID_PTR)NULL == pTemplate[i].pValue ) {
  1340.             /* Removing the attribute */
  1341.             newLength--;
  1342.           }
  1343.           break;
  1344.         }
  1345.       }
  1346.       if( j == n ) {
  1347.         /* Not found */
  1348.         newLength++;
  1349.       }
  1350.     }
  1351.     newTemplate = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE, newLength);
  1352.     if( (CK_ATTRIBUTE_PTR)NULL == newTemplate ) {
  1353.       NSSArena_Destroy(tmpArena);
  1354.       *pError = CKR_HOST_MEMORY;
  1355.       return (NSSCKFWObject *)NULL;
  1356.     }
  1357.     k = 0;
  1358.     for( j = 0; j < n; j++ ) {
  1359.       for( i = 0; i < ulAttributeCount; i++ ) {
  1360.         if( oldTypes[j] == pTemplate[i].type ) {
  1361.           if( (CK_VOID_PTR)NULL == pTemplate[i].pValue ) {
  1362.             /* This attribute is being deleted */
  1363.             ;
  1364.           } else {
  1365.             /* This attribute is being replaced */
  1366.             newTemplate[k].type = pTemplate[i].type;
  1367.             newTemplate[k].pValue = pTemplate[i].pValue;
  1368.             newTemplate[k].ulValueLen = pTemplate[i].ulValueLen;
  1369.             k++;
  1370.           }
  1371.           break;
  1372.         }
  1373.       }
  1374.       if( i == ulAttributeCount ) {
  1375.         /* This attribute is being copied over from the old object */
  1376.         NSSItem item, *it;
  1377.         item.size = 0;
  1378.         item.data = (void *)NULL;
  1379.         it = nssCKFWObject_GetAttribute(fwObject, oldTypes[j],
  1380.           &item, tmpArena, pError);
  1381.         if( (NSSItem *)NULL == it ) {
  1382.           if( CKR_OK == *pError ) {
  1383.             *pError = CKR_GENERAL_ERROR;
  1384.           }
  1385.           NSSArena_Destroy(tmpArena);
  1386.           return (NSSCKFWObject *)NULL;
  1387.         }
  1388.         newTemplate[k].type = oldTypes[j];
  1389.         newTemplate[k].pValue = it->data;
  1390.         newTemplate[k].ulValueLen = it->size;
  1391.         k++;
  1392.       }
  1393.     }
  1394.     /* assert that k == newLength */
  1395.     rv = nssCKFWSession_CreateObject(fwSession, newTemplate, newLength, pError);
  1396.     if( (NSSCKFWObject *)NULL == rv ) {
  1397.       if( CKR_OK == *pError ) {
  1398.         *pError = CKR_GENERAL_ERROR;
  1399.       }
  1400.       NSSArena_Destroy(tmpArena);
  1401.       return (NSSCKFWObject *)NULL;
  1402.     }
  1403.     NSSArena_Destroy(tmpArena);
  1404.     return rv;
  1405.   }
  1406. }
  1407. /*
  1408.  * nssCKFWSession_FindObjectsInit
  1409.  *
  1410.  */
  1411. NSS_IMPLEMENT NSSCKFWFindObjects *
  1412. nssCKFWSession_FindObjectsInit
  1413. (
  1414.   NSSCKFWSession *fwSession,
  1415.   CK_ATTRIBUTE_PTR pTemplate,
  1416.   CK_ULONG ulAttributeCount,
  1417.   CK_RV *pError
  1418. )
  1419. {
  1420.   NSSCKMDFindObjects *mdfo1 = (NSSCKMDFindObjects *)NULL;
  1421.   NSSCKMDFindObjects *mdfo2 = (NSSCKMDFindObjects *)NULL;
  1422. #ifdef NSSDEBUG
  1423.   if( (CK_RV *)NULL == pError ) {
  1424.     return (NSSCKFWFindObjects *)NULL;
  1425.   }
  1426.   *pError = nssCKFWSession_verifyPointer(fwSession);
  1427.   if( CKR_OK != *pError ) {
  1428.     return (NSSCKFWFindObjects *)NULL;
  1429.   }
  1430.   if( ((CK_ATTRIBUTE_PTR)NULL == pTemplate) && (ulAttributeCount != 0) ) {
  1431.     *pError = CKR_ARGUMENTS_BAD;
  1432.     return (NSSCKFWFindObjects *)NULL;
  1433.   }
  1434.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  1435.     *pError = CKR_GENERAL_ERROR;
  1436.     return (NSSCKFWFindObjects *)NULL;
  1437.   }
  1438. #endif /* NSSDEBUG */
  1439.   if( CK_TRUE != nssCKFWInstance_GetModuleHandlesSessionObjects(
  1440.                    fwSession->fwInstance) ) {
  1441.     CK_ULONG i;
  1442.     /*
  1443.      * Does the search criteria restrict us to token or session
  1444.      * objects?
  1445.      */
  1446.     for( i = 0; i < ulAttributeCount; i++ ) {
  1447.       if( CKA_TOKEN == pTemplate[i].type ) {
  1448.         /* Yes, it does. */
  1449.         CK_BBOOL isToken;
  1450.         if( sizeof(CK_BBOOL) != pTemplate[i].ulValueLen ) {
  1451.           *pError = CKR_ATTRIBUTE_VALUE_INVALID;
  1452.           return (NSSCKFWFindObjects *)NULL;
  1453.         }
  1454.         (void)nsslibc_memcpy(&isToken, pTemplate[i].pValue, sizeof(CK_BBOOL));
  1455.         if( CK_TRUE == isToken ) {
  1456.           /* Pass it on to the module's search routine */
  1457.           if( (void *)NULL == (void *)fwSession->mdSession->FindObjectsInit ) {
  1458.             goto wrap;
  1459.           }
  1460.           mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
  1461.                     fwSession, fwSession->mdToken, fwSession->fwToken,
  1462.                     fwSession->mdInstance, fwSession->fwInstance, 
  1463.                     pTemplate, ulAttributeCount, pError);
  1464.         } else {
  1465.           /* Do the search ourselves */
  1466.           mdfo1 = nssCKMDFindSessionObjects_Create(fwSession->fwToken, 
  1467.                     pTemplate, ulAttributeCount, pError);
  1468.         }
  1469.         if( (NSSCKMDFindObjects *)NULL == mdfo1 ) {
  1470.           if( CKR_OK == *pError ) {
  1471.             *pError = CKR_GENERAL_ERROR;
  1472.           }
  1473.           return (NSSCKFWFindObjects *)NULL;
  1474.         }
  1475.         
  1476.         goto wrap;
  1477.       }
  1478.     }
  1479.     if( i == ulAttributeCount ) {
  1480.       /* No, it doesn't.  Do a hybrid search. */
  1481.       mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
  1482.                 fwSession, fwSession->mdToken, fwSession->fwToken,
  1483.                 fwSession->mdInstance, fwSession->fwInstance, 
  1484.                 pTemplate, ulAttributeCount, pError);
  1485.       if( (NSSCKMDFindObjects *)NULL == mdfo1 ) {
  1486.         if( CKR_OK == *pError ) {
  1487.           *pError = CKR_GENERAL_ERROR;
  1488.         }
  1489.         return (NSSCKFWFindObjects *)NULL;
  1490.       }
  1491.       mdfo2 = nssCKMDFindSessionObjects_Create(fwSession->fwToken,
  1492.                 pTemplate, ulAttributeCount, pError);
  1493.       if( (NSSCKMDFindObjects *)NULL == mdfo2 ) {
  1494.         if( CKR_OK == *pError ) {
  1495.           *pError = CKR_GENERAL_ERROR;
  1496.         }
  1497.         if( (void *)NULL != (void *)mdfo1->Final ) {
  1498.           mdfo1->Final(mdfo1, (NSSCKFWFindObjects *)NULL, fwSession->mdSession,
  1499.             fwSession, fwSession->mdToken, fwSession->fwToken, 
  1500.             fwSession->mdInstance, fwSession->fwInstance);
  1501.         }
  1502.         return (NSSCKFWFindObjects *)NULL;
  1503.       }
  1504.       goto wrap;
  1505.     }
  1506.     /*NOTREACHED*/
  1507.   } else {
  1508.     /* Module handles all its own objects.  Pass on to module's search */
  1509.     mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
  1510.               fwSession, fwSession->mdToken, fwSession->fwToken,
  1511.               fwSession->mdInstance, fwSession->fwInstance, 
  1512.               pTemplate, ulAttributeCount, pError);
  1513.     if( (NSSCKMDFindObjects *)NULL == mdfo1 ) {
  1514.       if( CKR_OK == *pError ) {
  1515.         *pError = CKR_GENERAL_ERROR;
  1516.       }
  1517.       return (NSSCKFWFindObjects *)NULL;
  1518.     }
  1519.     goto wrap;
  1520.   }
  1521.  wrap:
  1522.   return nssCKFWFindObjects_Create(fwSession, fwSession->fwToken,
  1523.            fwSession->fwInstance, mdfo1, mdfo2, pError);
  1524. }
  1525. /*
  1526.  * nssCKFWSession_SeedRandom
  1527.  *
  1528.  */
  1529. NSS_IMPLEMENT CK_RV
  1530. nssCKFWSession_SeedRandom
  1531. (
  1532.   NSSCKFWSession *fwSession,
  1533.   NSSItem *seed
  1534. )
  1535. {
  1536.   CK_RV error = CKR_OK;
  1537. #ifdef NSSDEBUG
  1538.   error = nssCKFWSession_verifyPointer(fwSession);
  1539.   if( CKR_OK != error ) {
  1540.     return error;
  1541.   }
  1542.   if( (NSSItem *)NULL == seed ) {
  1543.     return CKR_ARGUMENTS_BAD;
  1544.   }
  1545.   if( (void *)NULL == seed->data ) {
  1546.     return CKR_ARGUMENTS_BAD;
  1547.   }
  1548.   if( 0 == seed->size ) {
  1549.     return CKR_ARGUMENTS_BAD;
  1550.   }
  1551.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  1552.     return CKR_GENERAL_ERROR;
  1553.   }
  1554. #endif /* NSSDEBUG */
  1555.   if( (void *)NULL == (void *)fwSession->mdSession->SeedRandom ) {
  1556.     return CKR_RANDOM_SEED_NOT_SUPPORTED;
  1557.   }
  1558.   error = fwSession->mdSession->SeedRandom(fwSession->mdSession, fwSession,
  1559.     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  1560.     fwSession->fwInstance, seed);
  1561.   return error;
  1562. }
  1563. /*
  1564.  * nssCKFWSession_GetRandom
  1565.  *
  1566.  */
  1567. NSS_IMPLEMENT CK_RV
  1568. nssCKFWSession_GetRandom
  1569. (
  1570.   NSSCKFWSession *fwSession,
  1571.   NSSItem *buffer
  1572. )
  1573. {
  1574.   CK_RV error = CKR_OK;
  1575. #ifdef NSSDEBUG
  1576.   error = nssCKFWSession_verifyPointer(fwSession);
  1577.   if( CKR_OK != error ) {
  1578.     return error;
  1579.   }
  1580.   if( (NSSItem *)NULL == buffer ) {
  1581.     return CKR_ARGUMENTS_BAD;
  1582.   }
  1583.   if( (void *)NULL == buffer->data ) {
  1584.     return CKR_ARGUMENTS_BAD;
  1585.   }
  1586.   if( (NSSCKMDSession *)NULL == fwSession->mdSession ) {
  1587.     return CKR_GENERAL_ERROR;
  1588.   }
  1589. #endif /* NSSDEBUG */
  1590.   if( (void *)NULL == (void *)fwSession->mdSession->GetRandom ) {
  1591.     if( CK_TRUE == nssCKFWToken_GetHasRNG(fwSession->fwToken) ) {
  1592.       return CKR_GENERAL_ERROR;
  1593.     } else {
  1594.       return CKR_RANDOM_NO_RNG;
  1595.     }
  1596.   }
  1597.   if( 0 == buffer->size ) {
  1598.     return CKR_OK;
  1599.   }
  1600.   error = fwSession->mdSession->GetRandom(fwSession->mdSession, fwSession,
  1601.     fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  1602.     fwSession->fwInstance, buffer);
  1603.   return error;
  1604. }
  1605. /*
  1606.  * NSSCKFWSession_GetMDSession
  1607.  *
  1608.  */
  1609. NSS_IMPLEMENT NSSCKMDSession *
  1610. NSSCKFWSession_GetMDSession
  1611. (
  1612.   NSSCKFWSession *fwSession
  1613. )
  1614. {
  1615. #ifdef DEBUG
  1616.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  1617.     return (NSSCKMDSession *)NULL;
  1618.   }
  1619. #endif /* DEBUG */
  1620.   return nssCKFWSession_GetMDSession(fwSession);
  1621. }
  1622. /*
  1623.  * NSSCKFWSession_GetArena
  1624.  *
  1625.  */
  1626. NSS_IMPLEMENT NSSArena *
  1627. NSSCKFWSession_GetArena
  1628. (
  1629.   NSSCKFWSession *fwSession,
  1630.   CK_RV *pError
  1631. )
  1632. {
  1633. #ifdef DEBUG
  1634.   if( (CK_RV *)NULL == pError ) {
  1635.     return (NSSArena *)NULL;
  1636.   }
  1637.   *pError = nssCKFWSession_verifyPointer(fwSession);
  1638.   if( CKR_OK != *pError ) {
  1639.     return (NSSArena *)NULL;
  1640.   }
  1641. #endif /* DEBUG */
  1642.   return nssCKFWSession_GetArena(fwSession, pError);
  1643. }
  1644. /*
  1645.  * NSSCKFWSession_CallNotification
  1646.  *
  1647.  */
  1648. NSS_IMPLEMENT CK_RV
  1649. NSSCKFWSession_CallNotification
  1650. (
  1651.   NSSCKFWSession *fwSession,
  1652.   CK_NOTIFICATION event
  1653. )
  1654. {
  1655.   CK_RV error = CKR_OK;
  1656. #ifdef DEBUG
  1657.   error = nssCKFWSession_verifyPointer(fwSession);
  1658.   if( CKR_OK != error ) {
  1659.     return error;
  1660.   }
  1661. #endif /* DEBUG */
  1662.   return nssCKFWSession_CallNotification(fwSession, event);
  1663. }
  1664. /*
  1665.  * NSSCKFWSession_IsRWSession
  1666.  *
  1667.  */
  1668. NSS_IMPLEMENT CK_BBOOL
  1669. NSSCKFWSession_IsRWSession
  1670. (
  1671.   NSSCKFWSession *fwSession
  1672. )
  1673. {
  1674. #ifdef DEBUG
  1675.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  1676.     return CK_FALSE;
  1677.   }
  1678. #endif /* DEBUG */
  1679.   return nssCKFWSession_IsRWSession(fwSession);
  1680. }
  1681. /*
  1682.  * NSSCKFWSession_IsSO
  1683.  *
  1684.  */
  1685. NSS_IMPLEMENT CK_BBOOL
  1686. NSSCKFWSession_IsSO
  1687. (
  1688.   NSSCKFWSession *fwSession
  1689. )
  1690. {
  1691. #ifdef DEBUG
  1692.   if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  1693.     return CK_FALSE;
  1694.   }
  1695. #endif /* DEBUG */
  1696.   return nssCKFWSession_IsSO(fwSession);
  1697. }