Back to index

lightning-sunbird  0.9+nobinonly
token.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #ifdef DEBUG
00038 static const char CVS_ID[] = "@(#) $RCSfile: token.c,v $ $Revision: 1.10 $ $Date: 2005/01/20 02:25:45 $";
00039 #endif /* DEBUG */
00040 
00041 /*
00042  * token.c
00043  *
00044  * This file implements the NSSCKFWToken type and methods.
00045  */
00046 
00047 #ifndef CK_T
00048 #include "ck.h"
00049 #endif /* CK_T */
00050 
00051 /*
00052  * NSSCKFWToken
00053  *
00054  *  -- create/destroy --
00055  *  nssCKFWToken_Create
00056  *  nssCKFWToken_Destroy
00057  *
00058  *  -- public accessors --
00059  *  NSSCKFWToken_GetMDToken
00060  *  NSSCKFWToken_GetFWSlot
00061  *  NSSCKFWToken_GetMDSlot
00062  *  NSSCKFWToken_GetSessionState
00063  *
00064  *  -- implement public accessors --
00065  *  nssCKFWToken_GetMDToken
00066  *  nssCKFWToken_GetFWSlot
00067  *  nssCKFWToken_GetMDSlot
00068  *  nssCKFWToken_GetSessionState
00069  *  nssCKFWToken_SetSessionState
00070  *
00071  *  -- private accessors --
00072  *  nssCKFWToken_SetSessionState
00073  *  nssCKFWToken_RemoveSession
00074  *  nssCKFWToken_CloseAllSessions
00075  *  nssCKFWToken_GetSessionCount
00076  *  nssCKFWToken_GetRwSessionCount
00077  *  nssCKFWToken_GetRoSessionCount
00078  *  nssCKFWToken_GetSessionObjectHash
00079  *  nssCKFWToken_GetMDObjectHash
00080  *  nssCKFWToken_GetObjectHandleHash
00081  *
00082  *  -- module fronts --
00083  *  nssCKFWToken_InitToken
00084  *  nssCKFWToken_GetLabel
00085  *  nssCKFWToken_GetManufacturerID
00086  *  nssCKFWToken_GetModel
00087  *  nssCKFWToken_GetSerialNumber
00088  *  nssCKFWToken_GetHasRNG
00089  *  nssCKFWToken_GetIsWriteProtected
00090  *  nssCKFWToken_GetLoginRequired
00091  *  nssCKFWToken_GetUserPinInitialized
00092  *  nssCKFWToken_GetRestoreKeyNotNeeded
00093  *  nssCKFWToken_GetHasClockOnToken
00094  *  nssCKFWToken_GetHasProtectedAuthenticationPath
00095  *  nssCKFWToken_GetSupportsDualCryptoOperations
00096  *  nssCKFWToken_GetMaxSessionCount
00097  *  nssCKFWToken_GetMaxRwSessionCount
00098  *  nssCKFWToken_GetMaxPinLen
00099  *  nssCKFWToken_GetMinPinLen
00100  *  nssCKFWToken_GetTotalPublicMemory
00101  *  nssCKFWToken_GetFreePublicMemory
00102  *  nssCKFWToken_GetTotalPrivateMemory
00103  *  nssCKFWToken_GetFreePrivateMemory
00104  *  nssCKFWToken_GetHardwareVersion
00105  *  nssCKFWToken_GetFirmwareVersion
00106  *  nssCKFWToken_GetUTCTime
00107  *  nssCKFWToken_OpenSession
00108  *  nssCKFWToken_GetMechanismCount
00109  *  nssCKFWToken_GetMechanismTypes
00110  *  nssCKFWToken_GetMechanism
00111  */
00112 
00113 struct NSSCKFWTokenStr {
00114   NSSCKFWMutex *mutex;
00115   NSSArena *arena;
00116   NSSCKMDToken *mdToken;
00117   NSSCKFWSlot *fwSlot;
00118   NSSCKMDSlot *mdSlot;
00119   NSSCKFWInstance *fwInstance;
00120   NSSCKMDInstance *mdInstance;
00121 
00122   /*
00123    * Everything above is set at creation time, and then not modified.
00124    * The invariants the mutex protects are:
00125    *
00126    * 1) Each of the cached descriptions (versions, etc.) are in an
00127    *    internally consistant state.
00128    *
00129    * 2) The session counts and hashes are consistant.
00130    *
00131    * 3) The object hashes are consistant.
00132    *
00133    * Note that the calls accessing the cached descriptions will call
00134    * the NSSCKMDToken methods with the mutex locked.  Those methods
00135    * may then call the public NSSCKFWToken routines.  Those public
00136    * routines only access the constant data above and the atomic
00137    * CK_STATE session state variable below, so there's no problem.
00138    * But be careful if you add to this object; mutexes are in
00139    * general not reentrant, so don't create deadlock situations.
00140    */
00141 
00142   NSSUTF8 *label;
00143   NSSUTF8 *manufacturerID;
00144   NSSUTF8 *model;
00145   NSSUTF8 *serialNumber;
00146   CK_VERSION hardwareVersion;
00147   CK_VERSION firmwareVersion;
00148 
00149   CK_ULONG sessionCount;
00150   CK_ULONG rwSessionCount;
00151   nssCKFWHash *sessions;
00152   nssCKFWHash *sessionObjectHash;
00153   nssCKFWHash *mdObjectHash;
00154 
00155   CK_STATE state;
00156 };
00157 
00158 #ifdef DEBUG
00159 /*
00160  * But first, the pointer-tracking stuff.
00161  *
00162  * NOTE: the pointer-tracking support in NSS/base currently relies
00163  * upon NSPR's CallOnce support.  That, however, relies upon NSPR's
00164  * locking, which is tied into the runtime.  We need a pointer-tracker
00165  * implementation that uses the locks supplied through C_Initialize.
00166  * That support, however, can be filled in later.  So for now, I'll
00167  * just do this routines as no-ops.
00168  */
00169 
00170 static CK_RV
00171 token_add_pointer
00172 (
00173   const NSSCKFWToken *fwToken
00174 )
00175 {
00176   return CKR_OK;
00177 }
00178 
00179 static CK_RV
00180 token_remove_pointer
00181 (
00182   const NSSCKFWToken *fwToken
00183 )
00184 {
00185   return CKR_OK;
00186 }
00187 
00188 NSS_IMPLEMENT CK_RV
00189 nssCKFWToken_verifyPointer
00190 (
00191   const NSSCKFWToken *fwToken
00192 )
00193 {
00194   return CKR_OK;
00195 }
00196 
00197 #endif /* DEBUG */
00198 
00199 /*
00200  * nssCKFWToken_Create
00201  *
00202  */
00203 NSS_IMPLEMENT NSSCKFWToken *
00204 nssCKFWToken_Create
00205 (
00206   NSSCKFWSlot *fwSlot,
00207   NSSCKMDToken *mdToken,
00208   CK_RV *pError
00209 )
00210 {
00211   NSSArena *arena = (NSSArena *)NULL;
00212   NSSCKFWToken *fwToken = (NSSCKFWToken *)NULL;
00213   CK_BBOOL called_setup = CK_FALSE;
00214 
00215   /*
00216    * We have already verified the arguments in nssCKFWSlot_GetToken.
00217    */
00218 
00219   arena = NSSArena_Create();
00220   if( (NSSArena *)NULL == arena ) {
00221     *pError = CKR_HOST_MEMORY;
00222     goto loser;
00223   }
00224 
00225   fwToken = nss_ZNEW(arena, NSSCKFWToken);
00226   if( (NSSCKFWToken *)NULL == fwToken ) {
00227     *pError = CKR_HOST_MEMORY;
00228     goto loser;
00229   }    
00230 
00231   fwToken->arena = arena;
00232   fwToken->mdToken = mdToken;
00233   fwToken->fwSlot = fwSlot;
00234   fwToken->fwInstance = nssCKFWSlot_GetFWInstance(fwSlot);
00235   fwToken->mdInstance = nssCKFWSlot_GetMDInstance(fwSlot);
00236   fwToken->state = CKS_RO_PUBLIC_SESSION; /* some default */
00237   fwToken->sessionCount = 0;
00238   fwToken->rwSessionCount = 0;
00239 
00240   fwToken->mutex = nssCKFWInstance_CreateMutex(fwToken->fwInstance, arena, pError);
00241   if( (NSSCKFWMutex *)NULL == fwToken->mutex ) {
00242     if( CKR_OK == *pError ) {
00243       *pError = CKR_GENERAL_ERROR;
00244     }
00245     goto loser;
00246   }
00247 
00248   fwToken->sessions = nssCKFWHash_Create(fwToken->fwInstance, arena, pError);
00249   if( (nssCKFWHash *)NULL == fwToken->sessions ) {
00250     if( CKR_OK == *pError ) {
00251       *pError = CKR_GENERAL_ERROR;
00252     }
00253     goto loser;
00254   }
00255 
00256   if( CK_TRUE != nssCKFWInstance_GetModuleHandlesSessionObjects(
00257                    fwToken->fwInstance) ) {
00258     fwToken->sessionObjectHash = nssCKFWHash_Create(fwToken->fwInstance, 
00259                                    arena, pError);
00260     if( (nssCKFWHash *)NULL == fwToken->sessionObjectHash ) {
00261       if( CKR_OK == *pError ) {
00262         *pError = CKR_GENERAL_ERROR;
00263       }
00264       goto loser;
00265     }
00266   }
00267 
00268   fwToken->mdObjectHash = nssCKFWHash_Create(fwToken->fwInstance, 
00269                             arena, pError);
00270   if( (nssCKFWHash *)NULL == fwToken->mdObjectHash ) {
00271     if( CKR_OK == *pError ) {
00272       *pError = CKR_GENERAL_ERROR;
00273     }
00274     goto loser;
00275   }
00276 
00277   /* More here */
00278 
00279   if( (void *)NULL != (void *)mdToken->Setup ) {
00280     *pError = mdToken->Setup(mdToken, fwToken, fwToken->mdInstance, fwToken->fwInstance);
00281     if( CKR_OK != *pError ) {
00282       goto loser;
00283     }
00284   }
00285 
00286   called_setup = CK_TRUE;
00287 
00288 #ifdef DEBUG
00289   *pError = token_add_pointer(fwToken);
00290   if( CKR_OK != *pError ) {
00291     goto loser;
00292   }
00293 #endif /* DEBUG */
00294 
00295   *pError = CKR_OK;
00296   return fwToken;
00297 
00298  loser:
00299 
00300   if( CK_TRUE == called_setup ) {
00301     if( (void *)NULL != (void *)mdToken->Invalidate ) {
00302       mdToken->Invalidate(mdToken, fwToken, fwToken->mdInstance, fwToken->fwInstance);
00303     }
00304   }
00305 
00306   if( (NSSArena *)NULL != arena ) {
00307     (void)NSSArena_Destroy(arena);
00308   }
00309 
00310   return (NSSCKFWToken *)NULL;
00311 }
00312 
00313 static void
00314 nss_ckfwtoken_session_iterator
00315 (
00316   const void *key,
00317   void *value,
00318   void *closure
00319 )
00320 {
00321   /*
00322    * Remember that the fwToken->mutex is locked
00323    */
00324   NSSCKFWSession *fwSession = (NSSCKFWSession *)value;
00325   (void)nssCKFWSession_Destroy(fwSession, CK_FALSE);
00326   return;
00327 }
00328 
00329 /*
00330  * nssCKFWToken_Destroy
00331  *
00332  */
00333 NSS_IMPLEMENT CK_RV
00334 nssCKFWToken_Destroy
00335 (
00336   NSSCKFWToken *fwToken
00337 )
00338 {
00339   CK_RV error = CKR_OK;
00340 
00341 #ifdef NSSDEBUG
00342   error = nssCKFWToken_verifyPointer(fwToken);
00343   if( CKR_OK != error ) {
00344     return error;
00345   }
00346 #endif /* NSSDEBUG */
00347 
00348   (void)nssCKFWMutex_Destroy(fwToken->mutex);
00349   
00350   if( (void *)NULL != (void *)fwToken->mdToken->Invalidate ) {
00351     fwToken->mdToken->Invalidate(fwToken->mdToken, fwToken,
00352       fwToken->mdInstance, fwToken->fwInstance);
00353   }
00354   /* we can destroy the list without locking now because no one else is 
00355    * referencing us (or _Destroy was invalidly called!)
00356    */
00357   nssCKFWHash_Iterate(fwToken->sessions, nss_ckfwtoken_session_iterator, 
00358                                                         (void *)NULL);
00359   nssCKFWHash_Destroy(fwToken->sessions);
00360 
00361   if (fwToken->sessionObjectHash) {
00362     nssCKFWHash_Destroy(fwToken->sessionObjectHash);
00363   }
00364   if (fwToken->mdObjectHash) {
00365     nssCKFWHash_Destroy(fwToken->mdObjectHash);
00366   }
00367 
00368   nssCKFWSlot_ClearToken(fwToken->fwSlot);
00369   
00370 #ifdef DEBUG
00371   error = token_remove_pointer(fwToken);
00372 #endif /* DEBUG */
00373 
00374   (void)NSSArena_Destroy(fwToken->arena);
00375   return error;
00376 }
00377 
00378 /*
00379  * nssCKFWToken_GetMDToken
00380  *
00381  */
00382 NSS_IMPLEMENT NSSCKMDToken *
00383 nssCKFWToken_GetMDToken
00384 (
00385   NSSCKFWToken *fwToken
00386 )
00387 {
00388 #ifdef NSSDEBUG
00389   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00390     return (NSSCKMDToken *)NULL;
00391   }
00392 #endif /* NSSDEBUG */
00393 
00394   return fwToken->mdToken;
00395 }
00396 
00397 /*
00398  * nssCKFWToken_GetArena
00399  *
00400  */
00401 NSS_IMPLEMENT NSSArena *
00402 nssCKFWToken_GetArena
00403 (
00404   NSSCKFWToken *fwToken,
00405   CK_RV *pError
00406 )
00407 {
00408 #ifdef NSSDEBUG
00409   if( (CK_RV *)NULL == pError ) {
00410     return (NSSArena *)NULL;
00411   }
00412 
00413   *pError = nssCKFWToken_verifyPointer(fwToken);
00414   if( CKR_OK != *pError ) {
00415     return (NSSArena *)NULL;
00416   }
00417 #endif /* NSSDEBUG */
00418 
00419   return fwToken->arena;
00420 }
00421 
00422 /*
00423  * nssCKFWToken_GetFWSlot
00424  *
00425  */
00426 NSS_IMPLEMENT NSSCKFWSlot *
00427 nssCKFWToken_GetFWSlot
00428 (
00429   NSSCKFWToken *fwToken
00430 )
00431 {
00432 #ifdef NSSDEBUG
00433   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00434     return (NSSCKFWSlot *)NULL;
00435   }
00436 #endif /* NSSDEBUG */
00437 
00438   return fwToken->fwSlot;
00439 }
00440 
00441 /*
00442  * nssCKFWToken_GetMDSlot
00443  *
00444  */
00445 NSS_IMPLEMENT NSSCKMDSlot *
00446 nssCKFWToken_GetMDSlot
00447 (
00448   NSSCKFWToken *fwToken
00449 )
00450 {
00451 #ifdef NSSDEBUG
00452   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00453     return (NSSCKMDSlot *)NULL;
00454   }
00455 #endif /* NSSDEBUG */
00456 
00457   return fwToken->mdSlot;
00458 }
00459 
00460 /*
00461  * nssCKFWToken_GetSessionState
00462  *
00463  */
00464 NSS_IMPLEMENT CK_STATE
00465 nssCKFWToken_GetSessionState
00466 (
00467   NSSCKFWToken *fwToken
00468 )
00469 {
00470 #ifdef NSSDEBUG
00471   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00472     return CKS_RO_PUBLIC_SESSION; /* whatever */
00473   }
00474 #endif /* NSSDEBUG */
00475 
00476   /*
00477    * BTW, do not lock the token in this method.
00478    */
00479 
00480   /*
00481    * Theoretically, there is no state if there aren't any
00482    * sessions open.  But then we'd need to worry about
00483    * reporting an error, etc.  What the heck-- let's just
00484    * revert to CKR_RO_PUBLIC_SESSION as the "default."
00485    */
00486 
00487   return fwToken->state;
00488 }
00489 
00490 /*
00491  * nssCKFWToken_InitToken
00492  *
00493  */
00494 NSS_IMPLEMENT CK_RV
00495 nssCKFWToken_InitToken
00496 (
00497   NSSCKFWToken *fwToken,
00498   NSSItem *pin,
00499   NSSUTF8 *label
00500 )
00501 {
00502   CK_RV error;
00503 
00504 #ifdef NSSDEBUG
00505   error = nssCKFWToken_verifyPointer(fwToken);
00506   if( CKR_OK != error ) {
00507     return CKR_ARGUMENTS_BAD;
00508   }
00509 #endif /* NSSDEBUG */
00510 
00511   error = nssCKFWMutex_Lock(fwToken->mutex);
00512   if( CKR_OK != error ) {
00513     return error;
00514   }
00515 
00516   if( fwToken->sessionCount > 0 ) {
00517     error = CKR_SESSION_EXISTS;
00518     goto done;
00519   }
00520 
00521   if( (void *)NULL == (void *)fwToken->mdToken->InitToken ) {
00522     error = CKR_DEVICE_ERROR;
00523     goto done;
00524   }
00525 
00526   if( (NSSItem *)NULL == pin ) {
00527     if( nssCKFWToken_GetHasProtectedAuthenticationPath(fwToken) ) {
00528       ; /* okay */
00529     } else {
00530       error = CKR_PIN_INCORRECT;
00531       goto done;
00532     }
00533   }
00534 
00535   if( (NSSUTF8 *)NULL == label ) {
00536     label = (NSSUTF8 *) "";
00537   }
00538 
00539   error = fwToken->mdToken->InitToken(fwToken->mdToken, fwToken,
00540             fwToken->mdInstance, fwToken->fwInstance, pin, label);
00541 
00542  done:
00543   (void)nssCKFWMutex_Unlock(fwToken->mutex);
00544   return error;
00545 }
00546 
00547 /*
00548  * nssCKFWToken_GetLabel
00549  *
00550  */
00551 NSS_IMPLEMENT CK_RV
00552 nssCKFWToken_GetLabel
00553 (
00554   NSSCKFWToken *fwToken,
00555   CK_CHAR label[32]
00556 )
00557 {
00558   CK_RV error = CKR_OK;
00559 
00560 #ifdef NSSDEBUG
00561   if( (CK_CHAR_PTR)NULL == label ) {
00562     return CKR_ARGUMENTS_BAD;
00563   }
00564 
00565   error = nssCKFWToken_verifyPointer(fwToken);
00566   if( CKR_OK != error ) {
00567     return error;
00568   }
00569 #endif /* NSSDEBUG */
00570 
00571   error = nssCKFWMutex_Lock(fwToken->mutex);
00572   if( CKR_OK != error ) {
00573     return error;
00574   }
00575 
00576   if( (NSSUTF8 *)NULL == fwToken->label ) {
00577     if( (void *)NULL != (void *)fwToken->mdToken->GetLabel ) {
00578       fwToken->label = fwToken->mdToken->GetLabel(fwToken->mdToken, fwToken,
00579         fwToken->mdInstance, fwToken->fwInstance, &error);
00580       if( ((NSSUTF8 *)NULL == fwToken->label) && (CKR_OK != error) ) {
00581         goto done;
00582       }
00583     } else {
00584       fwToken->label = (NSSUTF8 *) "";
00585     }
00586   }
00587 
00588   (void)nssUTF8_CopyIntoFixedBuffer(fwToken->label, (char *)label, 32, ' ');
00589   error = CKR_OK;
00590 
00591  done:
00592   (void)nssCKFWMutex_Unlock(fwToken->mutex);
00593   return error;
00594 }
00595 
00596 /*
00597  * nssCKFWToken_GetManufacturerID
00598  *
00599  */
00600 NSS_IMPLEMENT CK_RV
00601 nssCKFWToken_GetManufacturerID
00602 (
00603   NSSCKFWToken *fwToken,
00604   CK_CHAR manufacturerID[32]
00605 )
00606 {
00607   CK_RV error = CKR_OK;
00608 
00609 #ifdef NSSDEBUG
00610   if( (CK_CHAR_PTR)NULL == manufacturerID ) {
00611     return CKR_ARGUMENTS_BAD;
00612   }
00613 
00614   error = nssCKFWToken_verifyPointer(fwToken);
00615   if( CKR_OK != error ) {
00616     return error;
00617   }
00618 #endif /* NSSDEBUG */
00619 
00620   error = nssCKFWMutex_Lock(fwToken->mutex);
00621   if( CKR_OK != error ) {
00622     return error;
00623   }
00624 
00625   if( (NSSUTF8 *)NULL == fwToken->manufacturerID ) {
00626     if( (void *)NULL != (void *)fwToken->mdToken->GetManufacturerID ) {
00627       fwToken->manufacturerID = fwToken->mdToken->GetManufacturerID(fwToken->mdToken,
00628         fwToken, fwToken->mdInstance, fwToken->fwInstance, &error);
00629       if( ((NSSUTF8 *)NULL == fwToken->manufacturerID) && (CKR_OK != error) ) {
00630         goto done;
00631       }
00632     } else {
00633       fwToken->manufacturerID = (NSSUTF8 *)"";
00634     }
00635   }
00636 
00637   (void)nssUTF8_CopyIntoFixedBuffer(fwToken->manufacturerID, (char *)manufacturerID, 32, ' ');
00638   error = CKR_OK;
00639 
00640  done:
00641   (void)nssCKFWMutex_Unlock(fwToken->mutex);
00642   return error;
00643 }
00644 
00645 /*
00646  * nssCKFWToken_GetModel
00647  *
00648  */
00649 NSS_IMPLEMENT CK_RV
00650 nssCKFWToken_GetModel
00651 (
00652   NSSCKFWToken *fwToken,
00653   CK_CHAR model[16]
00654 )
00655 {
00656   CK_RV error = CKR_OK;
00657 
00658 #ifdef NSSDEBUG
00659   if( (CK_CHAR_PTR)NULL == model ) {
00660     return CKR_ARGUMENTS_BAD;
00661   }
00662 
00663   error = nssCKFWToken_verifyPointer(fwToken);
00664   if( CKR_OK != error ) {
00665     return error;
00666   }
00667 #endif /* NSSDEBUG */
00668 
00669   error = nssCKFWMutex_Lock(fwToken->mutex);
00670   if( CKR_OK != error ) {
00671     return error;
00672   }
00673 
00674   if( (NSSUTF8 *)NULL == fwToken->model ) {
00675     if( (void *)NULL != (void *)fwToken->mdToken->GetModel ) {
00676       fwToken->model = fwToken->mdToken->GetModel(fwToken->mdToken, fwToken,
00677         fwToken->mdInstance, fwToken->fwInstance, &error);
00678       if( ((NSSUTF8 *)NULL == fwToken->model) && (CKR_OK != error) ) {
00679         goto done;
00680       }
00681     } else {
00682       fwToken->model = (NSSUTF8 *)"";
00683     }
00684   }
00685 
00686   (void)nssUTF8_CopyIntoFixedBuffer(fwToken->model, (char *)model, 16, ' ');
00687   error = CKR_OK;
00688 
00689  done:
00690   (void)nssCKFWMutex_Unlock(fwToken->mutex);
00691   return error;
00692 }
00693 
00694 /*
00695  * nssCKFWToken_GetSerialNumber
00696  *
00697  */
00698 NSS_IMPLEMENT CK_RV
00699 nssCKFWToken_GetSerialNumber
00700 (
00701   NSSCKFWToken *fwToken,
00702   CK_CHAR serialNumber[16]
00703 )
00704 {
00705   CK_RV error = CKR_OK;
00706 
00707 #ifdef NSSDEBUG
00708   if( (CK_CHAR_PTR)NULL == serialNumber ) {
00709     return CKR_ARGUMENTS_BAD;
00710   }
00711 
00712   error = nssCKFWToken_verifyPointer(fwToken);
00713   if( CKR_OK != error ) {
00714     return error;
00715   }
00716 #endif /* NSSDEBUG */
00717 
00718   error = nssCKFWMutex_Lock(fwToken->mutex);
00719   if( CKR_OK != error ) {
00720     return error;
00721   }
00722 
00723   if( (NSSUTF8 *)NULL == fwToken->serialNumber ) {
00724     if( (void *)NULL != (void *)fwToken->mdToken->GetSerialNumber ) {
00725       fwToken->serialNumber = fwToken->mdToken->GetSerialNumber(fwToken->mdToken, 
00726         fwToken, fwToken->mdInstance, fwToken->fwInstance, &error);
00727       if( ((NSSUTF8 *)NULL == fwToken->serialNumber) && (CKR_OK != error) ) {
00728         goto done;
00729       }
00730     } else {
00731       fwToken->serialNumber = (NSSUTF8 *)"";
00732     }
00733   }
00734 
00735   (void)nssUTF8_CopyIntoFixedBuffer(fwToken->serialNumber, (char *)serialNumber, 16, ' ');
00736   error = CKR_OK;
00737 
00738  done:
00739   (void)nssCKFWMutex_Unlock(fwToken->mutex);
00740   return error;
00741 }
00742 
00743 
00744 /*
00745  * nssCKFWToken_GetHasRNG
00746  *
00747  */
00748 NSS_IMPLEMENT CK_BBOOL
00749 nssCKFWToken_GetHasRNG
00750 (
00751   NSSCKFWToken *fwToken
00752 )
00753 {
00754 #ifdef NSSDEBUG
00755   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00756     return CK_FALSE;
00757   }
00758 #endif /* NSSDEBUG */
00759 
00760   if( (void *)NULL == (void *)fwToken->mdToken->GetHasRNG ) {
00761     return CK_FALSE;
00762   }
00763 
00764   return fwToken->mdToken->GetHasRNG(fwToken->mdToken, fwToken, 
00765     fwToken->mdInstance, fwToken->fwInstance);
00766 }
00767 
00768 /*
00769  * nssCKFWToken_GetIsWriteProtected
00770  *
00771  */
00772 NSS_IMPLEMENT CK_BBOOL
00773 nssCKFWToken_GetIsWriteProtected
00774 (
00775   NSSCKFWToken *fwToken
00776 )
00777 {
00778 #ifdef NSSDEBUG
00779   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00780     return CK_FALSE;
00781   }
00782 #endif /* NSSDEBUG */
00783 
00784   if( (void *)NULL == (void *)fwToken->mdToken->GetIsWriteProtected ) {
00785     return CK_FALSE;
00786   }
00787 
00788   return fwToken->mdToken->GetIsWriteProtected(fwToken->mdToken, fwToken, 
00789     fwToken->mdInstance, fwToken->fwInstance);
00790 }
00791 
00792 /*
00793  * nssCKFWToken_GetLoginRequired
00794  *
00795  */
00796 NSS_IMPLEMENT CK_BBOOL
00797 nssCKFWToken_GetLoginRequired
00798 (
00799   NSSCKFWToken *fwToken
00800 )
00801 {
00802 #ifdef NSSDEBUG
00803   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00804     return CK_FALSE;
00805   }
00806 #endif /* NSSDEBUG */
00807 
00808   if( (void *)NULL == (void *)fwToken->mdToken->GetLoginRequired ) {
00809     return CK_FALSE;
00810   }
00811 
00812   return fwToken->mdToken->GetLoginRequired(fwToken->mdToken, fwToken, 
00813     fwToken->mdInstance, fwToken->fwInstance);
00814 }
00815 
00816 /*
00817  * nssCKFWToken_GetUserPinInitialized
00818  *
00819  */
00820 NSS_IMPLEMENT CK_BBOOL
00821 nssCKFWToken_GetUserPinInitialized
00822 (
00823   NSSCKFWToken *fwToken
00824 )
00825 {
00826 #ifdef NSSDEBUG
00827   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00828     return CK_FALSE;
00829   }
00830 #endif /* NSSDEBUG */
00831 
00832   if( (void *)NULL == (void *)fwToken->mdToken->GetUserPinInitialized ) {
00833     return CK_FALSE;
00834   }
00835 
00836   return fwToken->mdToken->GetUserPinInitialized(fwToken->mdToken, fwToken, 
00837     fwToken->mdInstance, fwToken->fwInstance);
00838 }
00839 
00840 /*
00841  * nssCKFWToken_GetRestoreKeyNotNeeded
00842  *
00843  */
00844 NSS_IMPLEMENT CK_BBOOL
00845 nssCKFWToken_GetRestoreKeyNotNeeded
00846 (
00847   NSSCKFWToken *fwToken
00848 )
00849 {
00850 #ifdef NSSDEBUG
00851   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00852     return CK_FALSE;
00853   }
00854 #endif /* NSSDEBUG */
00855 
00856   if( (void *)NULL == (void *)fwToken->mdToken->GetRestoreKeyNotNeeded ) {
00857     return CK_FALSE;
00858   }
00859 
00860   return fwToken->mdToken->GetRestoreKeyNotNeeded(fwToken->mdToken, fwToken, 
00861     fwToken->mdInstance, fwToken->fwInstance);
00862 }
00863 
00864 /*
00865  * nssCKFWToken_GetHasClockOnToken
00866  *
00867  */
00868 NSS_IMPLEMENT CK_BBOOL
00869 nssCKFWToken_GetHasClockOnToken
00870 (
00871   NSSCKFWToken *fwToken
00872 )
00873 {
00874 #ifdef NSSDEBUG
00875   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00876     return CK_FALSE;
00877   }
00878 #endif /* NSSDEBUG */
00879 
00880   if( (void *)NULL == (void *)fwToken->mdToken->GetHasClockOnToken ) {
00881     return CK_FALSE;
00882   }
00883 
00884   return fwToken->mdToken->GetHasClockOnToken(fwToken->mdToken, fwToken, 
00885     fwToken->mdInstance, fwToken->fwInstance);
00886 }
00887 
00888 /*
00889  * nssCKFWToken_GetHasProtectedAuthenticationPath
00890  *
00891  */
00892 NSS_IMPLEMENT CK_BBOOL
00893 nssCKFWToken_GetHasProtectedAuthenticationPath
00894 (
00895   NSSCKFWToken *fwToken
00896 )
00897 {
00898 #ifdef NSSDEBUG
00899   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00900     return CK_FALSE;
00901   }
00902 #endif /* NSSDEBUG */
00903 
00904   if( (void *)NULL == (void *)fwToken->mdToken->GetHasProtectedAuthenticationPath ) {
00905     return CK_FALSE;
00906   }
00907 
00908   return fwToken->mdToken->GetHasProtectedAuthenticationPath(fwToken->mdToken, 
00909     fwToken, fwToken->mdInstance, fwToken->fwInstance);
00910 }
00911 
00912 /*
00913  * nssCKFWToken_GetSupportsDualCryptoOperations
00914  *
00915  */
00916 NSS_IMPLEMENT CK_BBOOL
00917 nssCKFWToken_GetSupportsDualCryptoOperations
00918 (
00919   NSSCKFWToken *fwToken
00920 )
00921 {
00922 #ifdef NSSDEBUG
00923   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00924     return CK_FALSE;
00925   }
00926 #endif /* NSSDEBUG */
00927 
00928   if( (void *)NULL == (void *)fwToken->mdToken->GetSupportsDualCryptoOperations ) {
00929     return CK_FALSE;
00930   }
00931 
00932   return fwToken->mdToken->GetSupportsDualCryptoOperations(fwToken->mdToken, 
00933     fwToken, fwToken->mdInstance, fwToken->fwInstance);
00934 }
00935 
00936 /*
00937  * nssCKFWToken_GetMaxSessionCount
00938  *
00939  */
00940 NSS_IMPLEMENT CK_ULONG
00941 nssCKFWToken_GetMaxSessionCount
00942 (
00943   NSSCKFWToken *fwToken
00944 )
00945 {
00946 #ifdef NSSDEBUG
00947   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00948     return CK_UNAVAILABLE_INFORMATION;
00949   }
00950 #endif /* NSSDEBUG */
00951 
00952   if( (void *)NULL == (void *)fwToken->mdToken->GetMaxSessionCount ) {
00953     return CK_UNAVAILABLE_INFORMATION;
00954   }
00955 
00956   return fwToken->mdToken->GetMaxSessionCount(fwToken->mdToken, fwToken, 
00957     fwToken->mdInstance, fwToken->fwInstance);
00958 }
00959 
00960 /*
00961  * nssCKFWToken_GetMaxRwSessionCount
00962  *
00963  */
00964 NSS_IMPLEMENT CK_ULONG
00965 nssCKFWToken_GetMaxRwSessionCount
00966 (
00967   NSSCKFWToken *fwToken
00968 )
00969 {
00970 #ifdef NSSDEBUG
00971   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00972     return CK_UNAVAILABLE_INFORMATION;
00973   }
00974 #endif /* NSSDEBUG */
00975 
00976   if( (void *)NULL == (void *)fwToken->mdToken->GetMaxRwSessionCount ) {
00977     return CK_UNAVAILABLE_INFORMATION;
00978   }
00979 
00980   return fwToken->mdToken->GetMaxRwSessionCount(fwToken->mdToken, fwToken, 
00981     fwToken->mdInstance, fwToken->fwInstance);
00982 }
00983 
00984 /*
00985  * nssCKFWToken_GetMaxPinLen
00986  *
00987  */
00988 NSS_IMPLEMENT CK_ULONG
00989 nssCKFWToken_GetMaxPinLen
00990 (
00991   NSSCKFWToken *fwToken
00992 )
00993 {
00994 #ifdef NSSDEBUG
00995   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
00996     return CK_UNAVAILABLE_INFORMATION;
00997   }
00998 #endif /* NSSDEBUG */
00999 
01000   if( (void *)NULL == (void *)fwToken->mdToken->GetMaxPinLen ) {
01001     return CK_UNAVAILABLE_INFORMATION;
01002   }
01003 
01004   return fwToken->mdToken->GetMaxPinLen(fwToken->mdToken, fwToken, 
01005     fwToken->mdInstance, fwToken->fwInstance);
01006 }
01007 
01008 /*
01009  * nssCKFWToken_GetMinPinLen
01010  *
01011  */
01012 NSS_IMPLEMENT CK_ULONG
01013 nssCKFWToken_GetMinPinLen
01014 (
01015   NSSCKFWToken *fwToken
01016 )
01017 {
01018 #ifdef NSSDEBUG
01019   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01020     return CK_UNAVAILABLE_INFORMATION;
01021   }
01022 #endif /* NSSDEBUG */
01023 
01024   if( (void *)NULL == (void *)fwToken->mdToken->GetMinPinLen ) {
01025     return CK_UNAVAILABLE_INFORMATION;
01026   }
01027 
01028   return fwToken->mdToken->GetMinPinLen(fwToken->mdToken, fwToken, 
01029     fwToken->mdInstance, fwToken->fwInstance);
01030 }
01031 
01032 /*
01033  * nssCKFWToken_GetTotalPublicMemory
01034  *
01035  */
01036 NSS_IMPLEMENT CK_ULONG
01037 nssCKFWToken_GetTotalPublicMemory
01038 (
01039   NSSCKFWToken *fwToken
01040 )
01041 {
01042 #ifdef NSSDEBUG
01043   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01044     return CK_UNAVAILABLE_INFORMATION;
01045   }
01046 #endif /* NSSDEBUG */
01047 
01048   if( (void *)NULL == (void *)fwToken->mdToken->GetTotalPublicMemory ) {
01049     return CK_UNAVAILABLE_INFORMATION;
01050   }
01051 
01052   return fwToken->mdToken->GetTotalPublicMemory(fwToken->mdToken, fwToken, 
01053     fwToken->mdInstance, fwToken->fwInstance);
01054 }
01055 
01056 /*
01057  * nssCKFWToken_GetFreePublicMemory
01058  *
01059  */
01060 NSS_IMPLEMENT CK_ULONG
01061 nssCKFWToken_GetFreePublicMemory
01062 (
01063   NSSCKFWToken *fwToken
01064 )
01065 {
01066 #ifdef NSSDEBUG
01067   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01068     return CK_UNAVAILABLE_INFORMATION;
01069   }
01070 #endif /* NSSDEBUG */
01071 
01072   if( (void *)NULL == (void *)fwToken->mdToken->GetFreePublicMemory ) {
01073     return CK_UNAVAILABLE_INFORMATION;
01074   }
01075 
01076   return fwToken->mdToken->GetFreePublicMemory(fwToken->mdToken, fwToken, 
01077     fwToken->mdInstance, fwToken->fwInstance);
01078 }
01079 
01080 /*
01081  * nssCKFWToken_GetTotalPrivateMemory
01082  *
01083  */
01084 NSS_IMPLEMENT CK_ULONG
01085 nssCKFWToken_GetTotalPrivateMemory
01086 (
01087   NSSCKFWToken *fwToken
01088 )
01089 {
01090 #ifdef NSSDEBUG
01091   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01092     return CK_UNAVAILABLE_INFORMATION;
01093   }
01094 #endif /* NSSDEBUG */
01095 
01096   if( (void *)NULL == (void *)fwToken->mdToken->GetTotalPrivateMemory ) {
01097     return CK_UNAVAILABLE_INFORMATION;
01098   }
01099 
01100   return fwToken->mdToken->GetTotalPrivateMemory(fwToken->mdToken, fwToken, 
01101     fwToken->mdInstance, fwToken->fwInstance);
01102 }
01103 
01104 /*
01105  * nssCKFWToken_GetFreePrivateMemory
01106  *
01107  */
01108 NSS_IMPLEMENT CK_ULONG
01109 nssCKFWToken_GetFreePrivateMemory
01110 (
01111   NSSCKFWToken *fwToken
01112 )
01113 {
01114 #ifdef NSSDEBUG
01115   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01116     return CK_UNAVAILABLE_INFORMATION;
01117   }
01118 #endif /* NSSDEBUG */
01119 
01120   if( (void *)NULL == (void *)fwToken->mdToken->GetFreePrivateMemory ) {
01121     return CK_UNAVAILABLE_INFORMATION;
01122   }
01123 
01124   return fwToken->mdToken->GetFreePrivateMemory(fwToken->mdToken, fwToken, 
01125     fwToken->mdInstance, fwToken->fwInstance);
01126 }
01127 
01128 /*
01129  * nssCKFWToken_GetHardwareVersion
01130  *
01131  */
01132 NSS_IMPLEMENT CK_VERSION
01133 nssCKFWToken_GetHardwareVersion
01134 (
01135   NSSCKFWToken *fwToken
01136 )
01137 {
01138   CK_VERSION rv;
01139 
01140 #ifdef NSSDEBUG
01141   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01142     rv.major = rv.minor = 0;
01143     return rv;
01144   }
01145 #endif /* NSSDEBUG */
01146 
01147   if( CKR_OK != nssCKFWMutex_Lock(fwToken->mutex) ) {
01148     rv.major = rv.minor = 0;
01149     return rv;
01150   }
01151 
01152   if( (0 != fwToken->hardwareVersion.major) ||
01153       (0 != fwToken->hardwareVersion.minor) ) {
01154     rv = fwToken->hardwareVersion;
01155     goto done;
01156   }
01157 
01158   if( (void *)NULL != (void *)fwToken->mdToken->GetHardwareVersion ) {
01159     fwToken->hardwareVersion = fwToken->mdToken->GetHardwareVersion(
01160       fwToken->mdToken, fwToken, fwToken->mdInstance, fwToken->fwInstance);
01161   } else {
01162     fwToken->hardwareVersion.major = 0;
01163     fwToken->hardwareVersion.minor = 1;
01164   }
01165 
01166   rv = fwToken->hardwareVersion;
01167 
01168  done:
01169   (void)nssCKFWMutex_Unlock(fwToken->mutex);
01170   return rv;
01171 }
01172 
01173 /*
01174  * nssCKFWToken_GetFirmwareVersion
01175  *
01176  */
01177 NSS_IMPLEMENT CK_VERSION
01178 nssCKFWToken_GetFirmwareVersion
01179 (
01180   NSSCKFWToken *fwToken
01181 )
01182 {
01183   CK_VERSION rv;
01184 
01185 #ifdef NSSDEBUG
01186   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01187     rv.major = rv.minor = 0;
01188     return rv;
01189   }
01190 #endif /* NSSDEBUG */
01191 
01192   if( CKR_OK != nssCKFWMutex_Lock(fwToken->mutex) ) {
01193     rv.major = rv.minor = 0;
01194     return rv;
01195   }
01196 
01197   if( (0 != fwToken->firmwareVersion.major) ||
01198       (0 != fwToken->firmwareVersion.minor) ) {
01199     rv = fwToken->firmwareVersion;
01200     goto done;
01201   }
01202 
01203   if( (void *)NULL != (void *)fwToken->mdToken->GetFirmwareVersion ) {
01204     fwToken->firmwareVersion = fwToken->mdToken->GetFirmwareVersion(
01205       fwToken->mdToken, fwToken, fwToken->mdInstance, fwToken->fwInstance);
01206   } else {
01207     fwToken->firmwareVersion.major = 0;
01208     fwToken->firmwareVersion.minor = 1;
01209   }
01210 
01211   rv = fwToken->firmwareVersion;
01212 
01213  done:
01214   (void)nssCKFWMutex_Unlock(fwToken->mutex);
01215   return rv;
01216 }
01217 
01218 /*
01219  * nssCKFWToken_GetUTCTime
01220  *
01221  */
01222 NSS_IMPLEMENT CK_RV
01223 nssCKFWToken_GetUTCTime
01224 (
01225   NSSCKFWToken *fwToken,
01226   CK_CHAR utcTime[16]
01227 )
01228 {
01229   CK_RV error = CKR_OK;
01230 
01231 #ifdef NSSDEBUG
01232   error = nssCKFWToken_verifyPointer(fwToken);
01233   if( CKR_OK != error ) {
01234     return error;
01235   }
01236 
01237   if( (CK_CHAR_PTR)NULL == utcTime ) {
01238     return CKR_ARGUMENTS_BAD;
01239   }
01240 #endif /* DEBUG */
01241 
01242   if( CK_TRUE != nssCKFWToken_GetHasClockOnToken(fwToken) ) {
01243     /* return CKR_DEVICE_ERROR; */
01244     (void)nssUTF8_CopyIntoFixedBuffer((NSSUTF8 *)NULL, (char *)utcTime, 16, ' ');
01245     return CKR_OK;
01246   }
01247 
01248   if( (void *)NULL == (void *)fwToken->mdToken->GetUTCTime ) {
01249     /* It said it had one! */
01250     return CKR_GENERAL_ERROR;
01251   }
01252 
01253   error = fwToken->mdToken->GetUTCTime(fwToken->mdToken, fwToken, 
01254             fwToken->mdInstance, fwToken->fwInstance, utcTime);
01255   if( CKR_OK != error ) {
01256     return error;
01257   }
01258 
01259   /* Sanity-check the data */
01260   {
01261     /* Format is YYYYMMDDhhmmss00 */
01262     int i;
01263     int Y, M, D, h, m, s, z;
01264     static int dims[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
01265 
01266     for( i = 0; i < 16; i++ ) {
01267       if( (utcTime[i] < '0') || (utcTime[i] > '9') ) {
01268         goto badtime;
01269       }
01270     }
01271 
01272     Y = ((utcTime[ 0] - '0') * 1000) + ((utcTime[1] - '0') * 100) +
01273         ((utcTime[ 2] - '0') * 10) + (utcTime[ 3] - '0');
01274     M = ((utcTime[ 4] - '0') * 10) + (utcTime[ 5] - '0');
01275     D = ((utcTime[ 6] - '0') * 10) + (utcTime[ 7] - '0');
01276     h = ((utcTime[ 8] - '0') * 10) + (utcTime[ 9] - '0');
01277     m = ((utcTime[10] - '0') * 10) + (utcTime[11] - '0');
01278     s = ((utcTime[12] - '0') * 10) + (utcTime[13] - '0');
01279     z = ((utcTime[14] - '0') * 10) + (utcTime[15] - '0');
01280 
01281     if( (Y < 1990) || (Y > 3000) ) goto badtime; /* Y3K problem.  heh heh heh */
01282     if( (M < 1) || (M > 12) ) goto badtime;
01283     if( (D < 1) || (D > 31) ) goto badtime;
01284 
01285     if( D > dims[M-1] ) goto badtime; /* per-month check */
01286     if( (2 == M) && (((Y%4)||!(Y%100))&&(Y%400)) && (D > 28) ) goto badtime; /* leap years */
01287 
01288     if( (h < 0) || (h > 23) ) goto badtime;
01289     if( (m < 0) || (m > 60) ) goto badtime;
01290     if( (s < 0) || (s > 61) ) goto badtime;
01291 
01292     /* 60m and 60 or 61s is only allowed for leap seconds. */
01293     if( (60 == m) || (s >= 60) ) {
01294       if( (23 != h) || (60 != m) || (s < 60) ) goto badtime;
01295       /* leap seconds can only happen on June 30 or Dec 31.. I think */
01296       /* if( ((6 != M) || (30 != D)) && ((12 != M) || (31 != D)) ) goto badtime; */
01297     }
01298   }
01299 
01300   return CKR_OK;
01301 
01302  badtime:
01303   return CKR_GENERAL_ERROR;
01304 }
01305 
01306 /*
01307  * nssCKFWToken_OpenSession
01308  *
01309  */
01310 NSS_IMPLEMENT NSSCKFWSession *
01311 nssCKFWToken_OpenSession
01312 (
01313   NSSCKFWToken *fwToken,
01314   CK_BBOOL rw,
01315   CK_VOID_PTR pApplication,
01316   CK_NOTIFY Notify,
01317   CK_RV *pError
01318 )
01319 {
01320   NSSCKFWSession *fwSession = (NSSCKFWSession *)NULL;
01321   NSSCKMDSession *mdSession;
01322 
01323 #ifdef NSSDEBUG
01324   if( (CK_RV *)NULL == pError ) {
01325     return (NSSCKFWSession *)NULL;
01326   }
01327 
01328   *pError = nssCKFWToken_verifyPointer(fwToken);
01329   if( CKR_OK != *pError ) {
01330     return (NSSCKFWSession *)NULL;
01331   }
01332 
01333   switch( rw ) {
01334   case CK_TRUE:
01335   case CK_FALSE:
01336     break;
01337   default:
01338     *pError = CKR_ARGUMENTS_BAD;
01339     return (NSSCKFWSession *)NULL;
01340   }
01341 #endif /* NSSDEBUG */
01342 
01343   *pError = nssCKFWMutex_Lock(fwToken->mutex);
01344   if( CKR_OK != *pError ) {
01345     return (NSSCKFWSession *)NULL;
01346   }
01347 
01348   if( CK_TRUE == rw ) {
01349     /* Read-write session desired */
01350     if( CK_TRUE == nssCKFWToken_GetIsWriteProtected(fwToken) ) {
01351       *pError = CKR_TOKEN_WRITE_PROTECTED;
01352       goto done;
01353     }
01354   } else {
01355     /* Read-only session desired */
01356     if( CKS_RW_SO_FUNCTIONS == nssCKFWToken_GetSessionState(fwToken) ) {
01357       *pError = CKR_SESSION_READ_WRITE_SO_EXISTS;
01358       goto done;
01359     }
01360   }
01361 
01362   /* We could compare sesion counts to any limits we know of, I guess.. */
01363 
01364   if( (void *)NULL == (void *)fwToken->mdToken->OpenSession ) {
01365     /*
01366      * I'm not sure that the Module actually needs to implement
01367      * mdSessions -- the Framework can keep track of everything 
01368      * needed, really.  But I'll sort out that detail later..
01369      */
01370     *pError = CKR_GENERAL_ERROR;
01371     goto done;
01372   }
01373 
01374   fwSession = nssCKFWSession_Create(fwToken, rw, pApplication, Notify, pError);
01375   if( (NSSCKFWSession *)NULL == fwSession ) {
01376     if( CKR_OK == *pError ) {
01377       *pError = CKR_GENERAL_ERROR;
01378     }
01379     goto done;
01380   }
01381 
01382   mdSession = fwToken->mdToken->OpenSession(fwToken->mdToken, fwToken,
01383                 fwToken->mdInstance, fwToken->fwInstance, fwSession,
01384                 rw, pError);
01385   if( (NSSCKMDSession *)NULL == mdSession ) {
01386     (void)nssCKFWSession_Destroy(fwSession, CK_FALSE);
01387     if( CKR_OK == *pError ) {
01388       *pError = CKR_GENERAL_ERROR;
01389     }
01390     goto done;
01391   }
01392 
01393   *pError = nssCKFWSession_SetMDSession(fwSession, mdSession);
01394   if( CKR_OK != *pError ) {
01395     if( (void *)NULL != (void *)mdSession->Close ) {
01396       mdSession->Close(mdSession, fwSession, fwToken->mdToken, fwToken,
01397       fwToken->mdInstance, fwToken->fwInstance);
01398     }
01399     (void)nssCKFWSession_Destroy(fwSession, CK_FALSE);
01400     goto done;
01401   }
01402 
01403   *pError = nssCKFWHash_Add(fwToken->sessions, fwSession, fwSession);
01404   if( CKR_OK != *pError ) {
01405     (void)nssCKFWSession_Destroy(fwSession, CK_FALSE);
01406     fwSession = (NSSCKFWSession *)NULL;
01407     goto done;
01408   }
01409 
01410  done:
01411   (void)nssCKFWMutex_Unlock(fwToken->mutex);
01412   return fwSession;
01413 }
01414 
01415 /*
01416  * nssCKFWToken_GetMechanismCount
01417  *
01418  */
01419 NSS_IMPLEMENT CK_ULONG
01420 nssCKFWToken_GetMechanismCount
01421 (
01422   NSSCKFWToken *fwToken
01423 )
01424 {
01425 #ifdef NSSDEBUG
01426   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01427     return 0;
01428   }
01429 #endif /* NSSDEBUG */
01430 
01431   if( (void *)NULL == (void *)fwToken->mdToken->GetMechanismCount ) {
01432     return 0;
01433   }
01434 
01435   return fwToken->mdToken->GetMechanismCount(fwToken->mdToken, fwToken,
01436     fwToken->mdInstance, fwToken->fwInstance);
01437 }
01438 
01439 /*
01440  * nssCKFWToken_GetMechanismTypes
01441  *
01442  */
01443 NSS_IMPLEMENT CK_RV
01444 nssCKFWToken_GetMechanismTypes
01445 (
01446   NSSCKFWToken *fwToken,
01447   CK_MECHANISM_TYPE types[]
01448 )
01449 {
01450 #ifdef NSSDEBUG
01451   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01452     return CKR_ARGUMENTS_BAD;
01453   }
01454 
01455   if( (CK_MECHANISM_TYPE *)NULL == types ) {
01456     return CKR_ARGUMENTS_BAD;
01457   }
01458 #endif /* NSSDEBUG */
01459 
01460   if( (void *)NULL == (void *)fwToken->mdToken->GetMechanismTypes ) {
01461     /*
01462      * This should only be called with a sufficiently-large
01463      * "types" array, which can only be done if GetMechanismCount
01464      * is implemented.  If that's implemented (and returns nonzero),
01465      * then this should be too.  So return an error.
01466      */
01467     return CKR_GENERAL_ERROR;
01468   }
01469 
01470   return fwToken->mdToken->GetMechanismTypes(fwToken->mdToken, fwToken,
01471     fwToken->mdInstance, fwToken->fwInstance, types);
01472 }
01473 
01474 
01475 /*
01476  * nssCKFWToken_GetMechanism
01477  *
01478  */
01479 NSS_IMPLEMENT NSSCKFWMechanism *
01480 nssCKFWToken_GetMechanism
01481 (
01482   NSSCKFWToken *fwToken,
01483   CK_MECHANISM_TYPE which,
01484   CK_RV *pError
01485 )
01486 {
01487   /* XXX fgmr */
01488   return (NSSCKFWMechanism *)NULL;
01489 }
01490 
01491 NSS_IMPLEMENT CK_RV
01492 nssCKFWToken_SetSessionState
01493 (
01494   NSSCKFWToken *fwToken,
01495   CK_STATE newState
01496 )
01497 {
01498   CK_RV error = CKR_OK;
01499 
01500 #ifdef NSSDEBUG
01501   error = nssCKFWToken_verifyPointer(fwToken);
01502   if( CKR_OK != error ) {
01503     return error;
01504   }
01505 
01506   switch( newState ) {
01507   case CKS_RO_PUBLIC_SESSION:
01508   case CKS_RO_USER_FUNCTIONS:
01509   case CKS_RW_PUBLIC_SESSION:
01510   case CKS_RW_USER_FUNCTIONS:
01511   case CKS_RW_SO_FUNCTIONS:
01512     break;
01513   default:
01514     return CKR_ARGUMENTS_BAD;
01515   }
01516 #endif /* NSSDEBUG */
01517 
01518   error = nssCKFWMutex_Lock(fwToken->mutex);
01519   if( CKR_OK != error ) {
01520     return error;
01521   }
01522 
01523   fwToken->state = newState;
01524   (void)nssCKFWMutex_Unlock(fwToken->mutex);
01525   return CKR_OK;
01526 }
01527 
01528 /*
01529  * nssCKFWToken_RemoveSession
01530  *
01531  */
01532 NSS_IMPLEMENT CK_RV
01533 nssCKFWToken_RemoveSession
01534 (
01535   NSSCKFWToken *fwToken,
01536   NSSCKFWSession *fwSession
01537 )
01538 {
01539   CK_RV error = CKR_OK;
01540 
01541 #ifdef NSSDEBUG
01542   error = nssCKFWToken_verifyPointer(fwToken);
01543   if( CKR_OK != error ) {
01544     return error;
01545   }
01546 
01547   error = nssCKFWSession_verifyPointer(fwSession);
01548   if( CKR_OK != error ) {
01549     return error;
01550   }
01551 #endif /* NSSDEBUG */
01552 
01553   error = nssCKFWMutex_Lock(fwToken->mutex);
01554   if( CKR_OK != error ) {
01555     return error;
01556   }
01557 
01558   if( CK_TRUE != nssCKFWHash_Exists(fwToken->sessions, fwSession) ) {
01559     error = CKR_SESSION_HANDLE_INVALID;
01560     goto done;
01561   }
01562 
01563   nssCKFWHash_Remove(fwToken->sessions, fwSession);
01564   fwToken->sessionCount--;
01565 
01566   if( nssCKFWSession_IsRWSession(fwSession) ) {
01567     fwToken->rwSessionCount--;
01568   }
01569 
01570   if( 0 == fwToken->sessionCount ) {
01571     fwToken->rwSessionCount = 0; /* sanity */
01572     fwToken->state = CKS_RO_PUBLIC_SESSION; /* some default */
01573   }
01574 
01575   error = CKR_OK;
01576 
01577  done:
01578   (void)nssCKFWMutex_Unlock(fwToken->mutex);
01579   return error;
01580 }
01581 
01582 
01583 /*
01584  * nssCKFWToken_CloseAllSessions
01585  *
01586  */
01587 NSS_IMPLEMENT CK_RV
01588 nssCKFWToken_CloseAllSessions
01589 (
01590   NSSCKFWToken *fwToken
01591 )
01592 {
01593   CK_RV error = CKR_OK;
01594 
01595 #ifdef NSSDEBUG
01596   error = nssCKFWToken_verifyPointer(fwToken);
01597   if( CKR_OK != error ) {
01598     return error;
01599   }
01600 #endif /* NSSDEBUG */
01601 
01602   error = nssCKFWMutex_Lock(fwToken->mutex);
01603   if( CKR_OK != error ) {
01604     return error;
01605   }
01606 
01607   nssCKFWHash_Iterate(fwToken->sessions, nss_ckfwtoken_session_iterator, (void *)NULL);
01608 
01609   nssCKFWHash_Destroy(fwToken->sessions);
01610 
01611   fwToken->sessions = nssCKFWHash_Create(fwToken->fwInstance, fwToken->arena, &error);
01612   if( (nssCKFWHash *)NULL == fwToken->sessions ) {
01613     if( CKR_OK == error ) {
01614       error = CKR_GENERAL_ERROR;
01615     }
01616     goto done;
01617   }
01618 
01619   fwToken->state = CKS_RO_PUBLIC_SESSION; /* some default */
01620   fwToken->sessionCount = 0;
01621   fwToken->rwSessionCount = 0;
01622 
01623   error = CKR_OK;
01624 
01625  done:
01626   (void)nssCKFWMutex_Unlock(fwToken->mutex);
01627   return error;
01628 }
01629 
01630 /*
01631  * nssCKFWToken_GetSessionCount
01632  *
01633  */
01634 NSS_IMPLEMENT CK_ULONG
01635 nssCKFWToken_GetSessionCount
01636 (
01637   NSSCKFWToken *fwToken
01638 )
01639 {
01640   CK_ULONG rv;
01641 
01642 #ifdef NSSDEBUG
01643   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01644     return (CK_ULONG)0;
01645   }
01646 #endif /* NSSDEBUG */
01647 
01648   if( CKR_OK != nssCKFWMutex_Lock(fwToken->mutex) ) {
01649     return (CK_ULONG)0;
01650   }
01651 
01652   rv = fwToken->sessionCount;
01653   (void)nssCKFWMutex_Unlock(fwToken->mutex);
01654   return rv;
01655 }
01656 
01657 /*
01658  * nssCKFWToken_GetRwSessionCount
01659  *
01660  */
01661 NSS_IMPLEMENT CK_ULONG
01662 nssCKFWToken_GetRwSessionCount
01663 (
01664   NSSCKFWToken *fwToken
01665 )
01666 {
01667   CK_ULONG rv;
01668 
01669 #ifdef NSSDEBUG
01670   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01671     return (CK_ULONG)0;
01672   }
01673 #endif /* NSSDEBUG */
01674 
01675   if( CKR_OK != nssCKFWMutex_Lock(fwToken->mutex) ) {
01676     return (CK_ULONG)0;
01677   }
01678 
01679   rv = fwToken->rwSessionCount;
01680   (void)nssCKFWMutex_Unlock(fwToken->mutex);
01681   return rv;
01682 }
01683 
01684 /*
01685  * nssCKFWToken_GetRoSessionCount
01686  *
01687  */
01688 NSS_IMPLEMENT CK_ULONG
01689 nssCKFWToken_GetRoSessionCount
01690 (
01691   NSSCKFWToken *fwToken
01692 )
01693 {
01694   CK_ULONG rv;
01695 
01696 #ifdef NSSDEBUG
01697   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01698     return (CK_ULONG)0;
01699   }
01700 #endif /* NSSDEBUG */
01701 
01702   if( CKR_OK != nssCKFWMutex_Lock(fwToken->mutex) ) {
01703     return (CK_ULONG)0;
01704   }
01705 
01706   rv = fwToken->sessionCount - fwToken->rwSessionCount;
01707   (void)nssCKFWMutex_Unlock(fwToken->mutex);
01708   return rv;
01709 }
01710 
01711 /*
01712  * nssCKFWToken_GetSessionObjectHash
01713  *
01714  */
01715 NSS_IMPLEMENT nssCKFWHash *
01716 nssCKFWToken_GetSessionObjectHash
01717 (
01718   NSSCKFWToken *fwToken
01719 )
01720 {
01721 #ifdef NSSDEBUG
01722   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01723     return (nssCKFWHash *)NULL;
01724   }
01725 #endif /* NSSDEBUG */
01726 
01727   return fwToken->sessionObjectHash;
01728 }
01729 
01730 /*
01731  * nssCKFWToken_GetMDObjectHash
01732  *
01733  */
01734 NSS_IMPLEMENT nssCKFWHash *
01735 nssCKFWToken_GetMDObjectHash
01736 (
01737   NSSCKFWToken *fwToken
01738 )
01739 {
01740 #ifdef NSSDEBUG
01741   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01742     return (nssCKFWHash *)NULL;
01743   }
01744 #endif /* NSSDEBUG */
01745 
01746   return fwToken->mdObjectHash;
01747 }
01748 
01749 /*
01750  * nssCKFWToken_GetObjectHandleHash
01751  *
01752  */
01753 NSS_IMPLEMENT nssCKFWHash *
01754 nssCKFWToken_GetObjectHandleHash
01755 (
01756   NSSCKFWToken *fwToken
01757 )
01758 {
01759 #ifdef NSSDEBUG
01760   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01761     return (nssCKFWHash *)NULL;
01762   }
01763 #endif /* NSSDEBUG */
01764 
01765   return fwToken->mdObjectHash;
01766 }
01767 
01768 /*
01769  * NSSCKFWToken_GetMDToken
01770  *
01771  */
01772 
01773 NSS_IMPLEMENT NSSCKMDToken *
01774 NSSCKFWToken_GetMDToken
01775 (
01776   NSSCKFWToken *fwToken
01777 )
01778 {
01779 #ifdef DEBUG
01780   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01781     return (NSSCKMDToken *)NULL;
01782   }
01783 #endif /* DEBUG */
01784 
01785   return nssCKFWToken_GetMDToken(fwToken);
01786 }
01787 
01788 /*
01789  * NSSCKFWToken_GetArena
01790  *
01791  */
01792 
01793 NSS_IMPLEMENT NSSArena *
01794 NSSCKFWToken_GetArena
01795 (
01796   NSSCKFWToken *fwToken,
01797   CK_RV *pError
01798 )
01799 {
01800 #ifdef DEBUG
01801   if( (CK_RV *)NULL == pError ) {
01802     return (NSSArena *)NULL;
01803   }
01804 
01805   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01806     *pError = CKR_ARGUMENTS_BAD;
01807     return (NSSArena *)NULL;
01808   }
01809 #endif /* DEBUG */
01810 
01811   return nssCKFWToken_GetArena(fwToken, pError);
01812 }
01813 
01814 /*
01815  * NSSCKFWToken_GetFWSlot
01816  *
01817  */
01818 
01819 NSS_IMPLEMENT NSSCKFWSlot *
01820 NSSCKFWToken_GetFWSlot
01821 (
01822   NSSCKFWToken *fwToken
01823 )
01824 {
01825 #ifdef DEBUG
01826   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01827     return (NSSCKFWSlot *)NULL;
01828   }
01829 #endif /* DEBUG */
01830 
01831   return nssCKFWToken_GetFWSlot(fwToken);
01832 }
01833 
01834 /*
01835  * NSSCKFWToken_GetMDSlot
01836  *
01837  */
01838 
01839 NSS_IMPLEMENT NSSCKMDSlot *
01840 NSSCKFWToken_GetMDSlot
01841 (
01842   NSSCKFWToken *fwToken
01843 )
01844 {
01845 #ifdef DEBUG
01846   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01847     return (NSSCKMDSlot *)NULL;
01848   }
01849 #endif /* DEBUG */
01850 
01851   return nssCKFWToken_GetMDSlot(fwToken);
01852 }
01853 
01854 /*
01855  * NSSCKFWToken_GetSessionState
01856  *
01857  */
01858 
01859 NSS_IMPLEMENT CK_STATE
01860 NSSCKFWSession_GetSessionState
01861 (
01862   NSSCKFWToken *fwToken
01863 )
01864 {
01865 #ifdef DEBUG
01866   if( CKR_OK != nssCKFWToken_verifyPointer(fwToken) ) {
01867     return CKS_RO_PUBLIC_SESSION;
01868   }
01869 #endif /* DEBUG */
01870 
01871   return nssCKFWToken_GetSessionState(fwToken);
01872 }