Back to index

lightning-sunbird  0.9+nobinonly
object.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: object.c,v $ $Revision: 1.11 $ $Date: 2005/01/20 02:25:45 $";
00039 #endif /* DEBUG */
00040 
00041 /*
00042  * object.c
00043  *
00044  * This file implements the NSSCKFWObject type and methods.
00045  */
00046 
00047 #ifndef CK_T
00048 #include "ck.h"
00049 #endif /* CK_T */
00050 
00051 /*
00052  * NSSCKFWObject
00053  *
00054  * -- create/destroy --
00055  *  nssCKFWObject_Create
00056  *  nssCKFWObject_Finalize
00057  *  nssCKFWObject_Destroy
00058  *
00059  * -- public accessors --
00060  *  NSSCKFWObject_GetMDObject
00061  *  NSSCKFWObject_GetArena
00062  *  NSSCKFWObject_IsTokenObject
00063  *  NSSCKFWObject_GetAttributeCount
00064  *  NSSCKFWObject_GetAttributeTypes
00065  *  NSSCKFWObject_GetAttributeSize
00066  *  NSSCKFWObject_GetAttribute
00067  *  NSSCKFWObject_SetAttribute
00068  *  NSSCKFWObject_GetObjectSize
00069  *
00070  * -- implement public accessors --
00071  *  nssCKFWObject_GetMDObject
00072  *  nssCKFWObject_GetArena
00073  *
00074  * -- private accessors --
00075  *  nssCKFWObject_SetHandle
00076  *  nssCKFWObject_GetHandle
00077  *
00078  * -- module fronts --
00079  *  nssCKFWObject_IsTokenObject
00080  *  nssCKFWObject_GetAttributeCount
00081  *  nssCKFWObject_GetAttributeTypes
00082  *  nssCKFWObject_GetAttributeSize
00083  *  nssCKFWObject_GetAttribute
00084  *  nssCKFWObject_SetAttribute
00085  *  nssCKFWObject_GetObjectSize
00086  */
00087 
00088 struct NSSCKFWObjectStr {
00089   NSSCKFWMutex *mutex; /* merely to serialise the MDObject calls */
00090   NSSArena *arena;
00091   NSSCKMDObject *mdObject;
00092   NSSCKMDSession *mdSession;
00093   NSSCKFWSession *fwSession;
00094   NSSCKMDToken *mdToken;
00095   NSSCKFWToken *fwToken;
00096   NSSCKMDInstance *mdInstance;
00097   NSSCKFWInstance *fwInstance;
00098   CK_OBJECT_HANDLE hObject;
00099 };
00100 
00101 #ifdef DEBUG
00102 /*
00103  * But first, the pointer-tracking stuff.
00104  *
00105  * NOTE: the pointer-tracking support in NSS/base currently relies
00106  * upon NSPR's CallOnce support.  That, however, relies upon NSPR's
00107  * locking, which is tied into the runtime.  We need a pointer-tracker
00108  * implementation that uses the locks supplied through C_Initialize.
00109  * That support, however, can be filled in later.  So for now, I'll
00110  * just do this routines as no-ops.
00111  */
00112 
00113 static CK_RV
00114 object_add_pointer
00115 (
00116   const NSSCKFWObject *fwObject
00117 )
00118 {
00119   return CKR_OK;
00120 }
00121 
00122 static CK_RV
00123 object_remove_pointer
00124 (
00125   const NSSCKFWObject *fwObject
00126 )
00127 {
00128   return CKR_OK;
00129 }
00130 
00131 NSS_IMPLEMENT CK_RV
00132 nssCKFWObject_verifyPointer
00133 (
00134   const NSSCKFWObject *fwObject
00135 )
00136 {
00137   return CKR_OK;
00138 }
00139 
00140 #endif /* DEBUG */
00141 
00142 
00143 /*
00144  * nssCKFWObject_Create
00145  *
00146  */
00147 NSS_IMPLEMENT NSSCKFWObject *
00148 nssCKFWObject_Create
00149 (
00150   NSSArena *arena,
00151   NSSCKMDObject *mdObject,
00152   NSSCKFWSession *fwSession,
00153   NSSCKFWToken *fwToken,
00154   NSSCKFWInstance *fwInstance,
00155   CK_RV *pError
00156 )
00157 {
00158   NSSCKFWObject *fwObject;
00159   nssCKFWHash *mdObjectHash;
00160 
00161 #ifdef NSSDEBUG
00162   if( (CK_RV *)NULL == pError ) {
00163     return (NSSCKFWObject *)NULL;
00164   }
00165 
00166   if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
00167     *pError = CKR_ARGUMENTS_BAD;
00168     return (NSSCKFWObject *)NULL;
00169   }
00170 #endif /* NSSDEBUG */
00171 
00172   mdObjectHash = nssCKFWToken_GetMDObjectHash(fwToken);
00173   if( (nssCKFWHash *)NULL == mdObjectHash ) {
00174     *pError = CKR_GENERAL_ERROR;
00175     return (NSSCKFWObject *)NULL;
00176   }
00177 
00178   if( nssCKFWHash_Exists(mdObjectHash, mdObject) ) {
00179     fwObject = nssCKFWHash_Lookup(mdObjectHash, mdObject);
00180     return fwObject;
00181   }
00182 
00183   fwObject = nss_ZNEW(arena, NSSCKFWObject);
00184   if( (NSSCKFWObject *)NULL == fwObject ) {
00185     *pError = CKR_HOST_MEMORY;
00186     return (NSSCKFWObject *)NULL;
00187   }
00188 
00189   fwObject->arena = arena;
00190   fwObject->mdObject = mdObject;
00191   fwObject->fwSession = fwSession;
00192 
00193   if( (NSSCKFWSession *)NULL != fwSession ) {
00194     fwObject->mdSession = nssCKFWSession_GetMDSession(fwSession);
00195   }
00196 
00197   fwObject->fwToken = fwToken;
00198 
00199   if( (NSSCKFWToken *)NULL != fwToken ) {
00200     fwObject->mdToken = nssCKFWToken_GetMDToken(fwToken);
00201   }
00202 
00203   fwObject->fwInstance = fwInstance;
00204   fwObject->mdInstance = nssCKFWInstance_GetMDInstance(fwInstance);
00205   fwObject->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError);
00206   if( (NSSCKFWMutex *)NULL == fwObject->mutex ) {
00207     if( CKR_OK == *pError ) {
00208       *pError = CKR_GENERAL_ERROR;
00209     }
00210     return (NSSCKFWObject *)NULL;
00211   }
00212 
00213   *pError = nssCKFWHash_Add(mdObjectHash, mdObject, fwObject);
00214   if( CKR_OK != *pError ) {
00215     nss_ZFreeIf(fwObject);
00216     return (NSSCKFWObject *)NULL;
00217   }
00218 
00219 #ifdef DEBUG
00220   *pError = object_add_pointer(fwObject);
00221   if( CKR_OK != *pError ) {
00222     nssCKFWHash_Remove(mdObjectHash, mdObject);
00223     nss_ZFreeIf(fwObject);
00224     return (NSSCKFWObject *)NULL;
00225   }
00226 #endif /* DEBUG */
00227 
00228   *pError = CKR_OK;
00229   return fwObject;
00230 }
00231 
00232 /*
00233  * nssCKFWObject_Finalize
00234  *
00235  */
00236 NSS_IMPLEMENT void
00237 nssCKFWObject_Finalize
00238 (
00239   NSSCKFWObject *fwObject
00240 )
00241 {
00242   nssCKFWHash *mdObjectHash;
00243 
00244 #ifdef NSSDEBUG
00245   if( CKR_OK != nssCKFWObject_verifyPointer(fwObject) ) {
00246     return;
00247   }
00248 #endif /* NSSDEBUG */
00249 
00250   (void)nssCKFWMutex_Destroy(fwObject->mutex);
00251 
00252   if( (void *)NULL != (void *)fwObject->mdObject->Finalize ) {
00253     fwObject->mdObject->Finalize(fwObject->mdObject, fwObject,
00254       fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
00255       fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance);
00256   }
00257 
00258   mdObjectHash = nssCKFWToken_GetMDObjectHash(fwObject->fwToken);
00259   if( (nssCKFWHash *)NULL != mdObjectHash ) {
00260     nssCKFWHash_Remove(mdObjectHash, fwObject->mdObject);
00261   }
00262 
00263   nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject);
00264   nss_ZFreeIf(fwObject);
00265 
00266 #ifdef DEBUG
00267   (void)object_remove_pointer(fwObject);
00268 #endif /* DEBUG */
00269 
00270   return;
00271 }
00272 
00273 /*
00274  * nssCKFWObject_Destroy
00275  *
00276  */
00277 NSS_IMPLEMENT void
00278 nssCKFWObject_Destroy
00279 (
00280   NSSCKFWObject *fwObject
00281 )
00282 {
00283   nssCKFWHash *mdObjectHash;
00284 
00285 #ifdef NSSDEBUG
00286   if( CKR_OK != nssCKFWObject_verifyPointer(fwObject) ) {
00287     return;
00288   }
00289 #endif /* NSSDEBUG */
00290 
00291   (void)nssCKFWMutex_Destroy(fwObject->mutex);
00292 
00293   if( (void *)NULL != (void *)fwObject->mdObject->Destroy ) {
00294     fwObject->mdObject->Destroy(fwObject->mdObject, fwObject,
00295       fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
00296       fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance);
00297   }
00298 
00299   mdObjectHash = nssCKFWToken_GetMDObjectHash(fwObject->fwToken);
00300   if( (nssCKFWHash *)NULL != mdObjectHash ) {
00301     nssCKFWHash_Remove(mdObjectHash, fwObject->mdObject);
00302   }
00303 
00304   nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject);
00305   nss_ZFreeIf(fwObject);
00306 
00307 #ifdef DEBUG
00308   (void)object_remove_pointer(fwObject);
00309 #endif /* DEBUG */
00310 
00311   return;
00312 }
00313 
00314 /*
00315  * nssCKFWObject_GetMDObject
00316  *
00317  */
00318 NSS_IMPLEMENT NSSCKMDObject *
00319 nssCKFWObject_GetMDObject
00320 (
00321   NSSCKFWObject *fwObject
00322 )
00323 {
00324 #ifdef NSSDEBUG
00325   if( CKR_OK != nssCKFWObject_verifyPointer(fwObject) ) {
00326     return (NSSCKMDObject *)NULL;
00327   }
00328 #endif /* NSSDEBUG */
00329 
00330   return fwObject->mdObject;
00331 }
00332 
00333 /*
00334  * nssCKFWObject_GetArena
00335  *
00336  */
00337 NSS_IMPLEMENT NSSArena *
00338 nssCKFWObject_GetArena
00339 (
00340   NSSCKFWObject *fwObject,
00341   CK_RV *pError
00342 )
00343 {
00344 #ifdef NSSDEBUG
00345   if( (CK_RV *)NULL == pError ) {
00346     return (NSSArena *)NULL;
00347   }
00348 
00349   *pError = nssCKFWObject_verifyPointer(fwObject);
00350   if( CKR_OK != *pError ) {
00351     return (NSSArena *)NULL;
00352   }
00353 #endif /* NSSDEBUG */
00354 
00355   return fwObject->arena;
00356 }
00357 
00358 /*
00359  * nssCKFWObject_SetHandle
00360  *
00361  */
00362 NSS_IMPLEMENT CK_RV
00363 nssCKFWObject_SetHandle
00364 (
00365   NSSCKFWObject *fwObject,
00366   CK_OBJECT_HANDLE hObject
00367 )
00368 {
00369 #ifdef NSSDEBUG
00370   CK_RV error = CKR_OK;
00371 #endif /* NSSDEBUG */
00372 
00373 #ifdef NSSDEBUG
00374   error = nssCKFWObject_verifyPointer(fwObject);
00375   if( CKR_OK != error ) {
00376     return error;
00377   }
00378 #endif /* NSSDEBUG */
00379 
00380   if( (CK_OBJECT_HANDLE)0 != fwObject->hObject ) {
00381     return CKR_GENERAL_ERROR;
00382   }
00383 
00384   fwObject->hObject = hObject;
00385 
00386   return CKR_OK;
00387 }
00388 
00389 /*
00390  * nssCKFWObject_GetHandle
00391  *
00392  */
00393 NSS_IMPLEMENT CK_OBJECT_HANDLE
00394 nssCKFWObject_GetHandle
00395 (
00396   NSSCKFWObject *fwObject
00397 )
00398 {
00399 #ifdef NSSDEBUG
00400   if( CKR_OK != nssCKFWObject_verifyPointer(fwObject) ) {
00401     return (CK_OBJECT_HANDLE)0;
00402   }
00403 #endif /* NSSDEBUG */
00404 
00405   return fwObject->hObject;
00406 }
00407 
00408 /*
00409  * nssCKFWObject_IsTokenObject
00410  *
00411  */
00412 NSS_IMPLEMENT CK_BBOOL
00413 nssCKFWObject_IsTokenObject
00414 (
00415   NSSCKFWObject *fwObject
00416 )
00417 {
00418   CK_BBOOL b = CK_FALSE;
00419 
00420 #ifdef NSSDEBUG
00421   if( CKR_OK != nssCKFWObject_verifyPointer(fwObject) ) {
00422     return CK_FALSE;
00423   }
00424 #endif /* NSSDEBUG */
00425 
00426   if( (void *)NULL == (void *)fwObject->mdObject->IsTokenObject ) {
00427     NSSItem item;
00428     NSSItem *pItem;
00429     CK_RV rv = CKR_OK;
00430 
00431     item.data = (void *)&b;
00432     item.size = sizeof(b);
00433 
00434     pItem = nssCKFWObject_GetAttribute(fwObject, CKA_TOKEN, &item, 
00435       (NSSArena *)NULL, &rv);
00436     if( (NSSItem *)NULL == pItem ) {
00437       /* Error of some type */
00438       b = CK_FALSE;
00439       goto done;
00440     }
00441 
00442     goto done;
00443   }
00444 
00445   b = fwObject->mdObject->IsTokenObject(fwObject->mdObject, fwObject, 
00446     fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
00447     fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance);
00448 
00449  done:
00450   return b;
00451 }
00452 
00453 /*
00454  * nssCKFWObject_GetAttributeCount
00455  *
00456  */
00457 NSS_IMPLEMENT CK_ULONG
00458 nssCKFWObject_GetAttributeCount
00459 (
00460   NSSCKFWObject *fwObject,
00461   CK_RV *pError
00462 )
00463 {
00464   CK_ULONG rv;
00465 
00466 #ifdef NSSDEBUG
00467   if( (CK_RV *)NULL == pError ) {
00468     return (CK_ULONG)0;
00469   }
00470 
00471   *pError = nssCKFWObject_verifyPointer(fwObject);
00472   if( CKR_OK != *pError ) {
00473     return (CK_ULONG)0;
00474   }
00475 #endif /* NSSDEBUG */
00476 
00477   if( (void *)NULL == (void *)fwObject->mdObject->GetAttributeCount ) {
00478     *pError = CKR_GENERAL_ERROR;
00479     return (CK_ULONG)0;
00480   }
00481 
00482   *pError = nssCKFWMutex_Lock(fwObject->mutex);
00483   if( CKR_OK != *pError ) {
00484     return (CK_ULONG)0;
00485   }
00486 
00487   rv = fwObject->mdObject->GetAttributeCount(fwObject->mdObject, fwObject,
00488     fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, 
00489     fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
00490     pError);
00491 
00492   (void)nssCKFWMutex_Unlock(fwObject->mutex);
00493   return rv;
00494 }
00495 
00496 /*
00497  * nssCKFWObject_GetAttributeTypes
00498  *
00499  */
00500 NSS_IMPLEMENT CK_RV
00501 nssCKFWObject_GetAttributeTypes
00502 (
00503   NSSCKFWObject *fwObject,
00504   CK_ATTRIBUTE_TYPE_PTR typeArray,
00505   CK_ULONG ulCount
00506 )
00507 {
00508   CK_RV error = CKR_OK;
00509 
00510 #ifdef NSSDEBUG
00511   error = nssCKFWObject_verifyPointer(fwObject);
00512   if( CKR_OK != error ) {
00513     return error;
00514   }
00515 
00516   if( (CK_ATTRIBUTE_TYPE_PTR)NULL == typeArray ) {
00517     return CKR_ARGUMENTS_BAD;
00518   }
00519 #endif /* NSSDEBUG */
00520 
00521   if( (void *)NULL == (void *)fwObject->mdObject->GetAttributeTypes ) {
00522     return CKR_GENERAL_ERROR;
00523   }
00524 
00525   error = nssCKFWMutex_Lock(fwObject->mutex);
00526   if( CKR_OK != error ) {
00527     return error;
00528   }
00529 
00530   error = fwObject->mdObject->GetAttributeTypes(fwObject->mdObject, fwObject,
00531     fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, 
00532     fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
00533     typeArray, ulCount);
00534 
00535   (void)nssCKFWMutex_Unlock(fwObject->mutex);
00536   return error;
00537 }
00538 
00539 /*
00540  * nssCKFWObject_GetAttributeSize
00541  *
00542  */
00543 NSS_IMPLEMENT CK_ULONG
00544 nssCKFWObject_GetAttributeSize
00545 (
00546   NSSCKFWObject *fwObject,
00547   CK_ATTRIBUTE_TYPE attribute,
00548   CK_RV *pError
00549 )
00550 {
00551   CK_ULONG rv;
00552 
00553 #ifdef NSSDEBUG
00554   if( (CK_RV *)NULL == pError ) {
00555     return (CK_ULONG)0;
00556   }
00557 
00558   *pError = nssCKFWObject_verifyPointer(fwObject);
00559   if( CKR_OK != *pError ) {
00560     return (CK_ULONG)0;
00561   }
00562 #endif /* NSSDEBUG */
00563 
00564   if( (void *)NULL == (void *)fwObject->mdObject->GetAttributeSize ) {
00565     *pError = CKR_GENERAL_ERROR;
00566     return (CK_ULONG )0;
00567   }
00568 
00569   *pError = nssCKFWMutex_Lock(fwObject->mutex);
00570   if( CKR_OK != *pError ) {
00571     return (CK_ULONG)0;
00572   }
00573 
00574   rv = fwObject->mdObject->GetAttributeSize(fwObject->mdObject, fwObject,
00575     fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, 
00576     fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
00577     attribute, pError);
00578 
00579   (void)nssCKFWMutex_Unlock(fwObject->mutex);
00580   return rv;
00581 }
00582 
00583 /*
00584  * nssCKFWObject_GetAttribute
00585  *
00586  * Usual NSS allocation rules:
00587  * If itemOpt is not NULL, it will be returned; otherwise an NSSItem
00588  * will be allocated.  If itemOpt is not NULL but itemOpt->data is,
00589  * the buffer will be allocated; otherwise, the buffer will be used.
00590  * Any allocations will come from the optional arena, if one is
00591  * specified.
00592  */
00593 NSS_IMPLEMENT NSSItem *
00594 nssCKFWObject_GetAttribute
00595 (
00596   NSSCKFWObject *fwObject,
00597   CK_ATTRIBUTE_TYPE attribute,
00598   NSSItem *itemOpt,
00599   NSSArena *arenaOpt,
00600   CK_RV *pError
00601 )
00602 {
00603   NSSItem *rv = (NSSItem *)NULL;
00604   NSSCKFWItem mdItem;
00605 
00606 #ifdef NSSDEBUG
00607   if( (CK_RV *)NULL == pError ) {
00608     return (NSSItem *)NULL;
00609   }
00610 
00611   *pError = nssCKFWObject_verifyPointer(fwObject);
00612   if( CKR_OK != *pError ) {
00613     return (NSSItem *)NULL;
00614   }
00615 #endif /* NSSDEBUG */
00616 
00617   if( (void *)NULL == (void *)fwObject->mdObject->GetAttribute ) {
00618     *pError = CKR_GENERAL_ERROR;
00619     return (NSSItem *)NULL;
00620   }
00621 
00622   *pError = nssCKFWMutex_Lock(fwObject->mutex);
00623   if( CKR_OK != *pError ) {
00624     return (NSSItem *)NULL;
00625   }
00626 
00627   mdItem = fwObject->mdObject->GetAttribute(fwObject->mdObject, fwObject,
00628     fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, 
00629     fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
00630     attribute, pError);
00631 
00632   if( (NSSItem *)NULL == mdItem.item ) {
00633     if( CKR_OK == *pError ) {
00634       *pError = CKR_GENERAL_ERROR;
00635     }
00636 
00637     goto done;
00638   }
00639 
00640   if( (NSSItem *)NULL == itemOpt ) {
00641     rv = nss_ZNEW(arenaOpt, NSSItem);
00642     if( (NSSItem *)NULL == rv ) {
00643       *pError = CKR_HOST_MEMORY;
00644       goto done;
00645     }
00646   } else {
00647     rv = itemOpt;
00648   }
00649 
00650   if( (void *)NULL == rv->data ) {
00651     rv->size = mdItem.item->size;
00652     rv->data = nss_ZAlloc(arenaOpt, rv->size);
00653     if( (void *)NULL == rv->data ) {
00654       *pError = CKR_HOST_MEMORY;
00655       if( (NSSItem *)NULL == itemOpt ) {
00656         nss_ZFreeIf(rv);
00657       }
00658       rv = (NSSItem *)NULL;
00659       goto done;
00660     }
00661   } else {
00662     if( rv->size >= mdItem.item->size ) {
00663       rv->size = mdItem.item->size;
00664     } else {
00665       *pError = CKR_BUFFER_TOO_SMALL;
00666       /* Should we set rv->size to mdItem->size? */
00667       /* rv can't have been allocated */
00668       rv = (NSSItem *)NULL;
00669       goto done;
00670     }
00671   }
00672 
00673   (void)nsslibc_memcpy(rv->data, mdItem.item->data, rv->size);
00674 
00675   if (PR_TRUE == mdItem.needsFreeing) {
00676     PR_ASSERT(fwObject->mdObject->FreeAttribute);
00677     if (fwObject->mdObject->FreeAttribute) {
00678       *pError = fwObject->mdObject->FreeAttribute(&mdItem);
00679     }
00680   }
00681 
00682  done:
00683   (void)nssCKFWMutex_Unlock(fwObject->mutex);
00684   return rv;
00685 }
00686 
00687 /*
00688  * nssCKFWObject_SetAttribute
00689  *
00690  */
00691 NSS_IMPLEMENT CK_RV
00692 nssCKFWObject_SetAttribute
00693 (
00694   NSSCKFWObject *fwObject,
00695   CK_ATTRIBUTE_TYPE attribute,
00696   NSSItem *value
00697 )
00698 {
00699   CK_RV error = CKR_OK;
00700 
00701 #ifdef NSSDEBUG
00702   error = nssCKFWObject_verifyPointer(fwObject);
00703   if( CKR_OK != error ) {
00704     return error;
00705   }
00706 #endif /* NSSDEBUG */
00707 
00708   if( CKA_TOKEN == attribute ) {
00709     /*
00710      * We're changing from a session object to a token object or 
00711      * vice-versa.
00712      */
00713 
00714     CK_ATTRIBUTE a;
00715     NSSCKFWObject *newFwObject;
00716     NSSCKFWObject swab;
00717 
00718     a.type = CKA_TOKEN;
00719     a.pValue = value->data;
00720     a.ulValueLen = value->size;
00721 
00722     newFwObject = nssCKFWSession_CopyObject(fwObject->fwSession, fwObject,
00723                     &a, 1, &error);
00724     if( (NSSCKFWObject *)NULL == newFwObject ) {
00725       if( CKR_OK == error ) {
00726         error = CKR_GENERAL_ERROR;
00727       }
00728       return error;
00729     }
00730 
00731     /*
00732      * Actually, I bet the locking is worse than this.. this part of
00733      * the code could probably use some scrutiny and reworking.
00734      */
00735     error = nssCKFWMutex_Lock(fwObject->mutex);
00736     if( CKR_OK != error ) {
00737       nssCKFWObject_Destroy(newFwObject);
00738       return error;
00739     }
00740 
00741     error = nssCKFWMutex_Lock(newFwObject->mutex);
00742     if( CKR_OK != error ) {
00743       nssCKFWMutex_Unlock(fwObject->mutex);
00744       nssCKFWObject_Destroy(newFwObject);
00745       return error;
00746     }
00747 
00748     /* 
00749      * Now, we have our new object, but it has a new fwObject pointer,
00750      * while we have to keep the existing one.  So quick swap the contents.
00751      */
00752     swab = *fwObject;
00753     *fwObject = *newFwObject;
00754     *newFwObject = swab;
00755 
00756     /* But keep the mutexes the same */
00757     swab.mutex = fwObject->mutex;
00758     fwObject->mutex = newFwObject->mutex;
00759     newFwObject->mutex = swab.mutex;
00760 
00761     (void)nssCKFWMutex_Unlock(newFwObject->mutex);
00762     (void)nssCKFWMutex_Unlock(fwObject->mutex);
00763 
00764     /*
00765      * Either remove or add this to the list of session objects
00766      */
00767 
00768     if( CK_FALSE == *(CK_BBOOL *)value->data ) {
00769       /* 
00770        * New one is a session object, except since we "stole" the fwObject, it's
00771        * not in the list.  Add it.
00772        */
00773       nssCKFWSession_RegisterSessionObject(fwObject->fwSession, fwObject);
00774     } else {
00775       /*
00776        * New one is a token object, except since we "stole" the fwObject, it's
00777        * in the list.  Remove it.
00778        */
00779       nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject);
00780     }
00781 
00782     /*
00783      * Now delete the old object.  Remember the names have changed.
00784      */
00785     nssCKFWObject_Destroy(newFwObject);
00786 
00787     return CKR_OK;
00788   } else {
00789     /*
00790      * An "ordinary" change.
00791      */
00792     if( (void *)NULL == (void *)fwObject->mdObject->SetAttribute ) {
00793       /* We could fake it with copying, like above.. later */
00794       return CKR_ATTRIBUTE_READ_ONLY;
00795     }
00796 
00797     error = nssCKFWMutex_Lock(fwObject->mutex);
00798     if( CKR_OK != error ) {
00799       return error;
00800     }
00801 
00802     error = fwObject->mdObject->SetAttribute(fwObject->mdObject, fwObject,
00803       fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, 
00804       fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
00805       attribute, value);
00806 
00807     (void)nssCKFWMutex_Unlock(fwObject->mutex);
00808 
00809     return error;
00810   }
00811 }
00812 
00813 /*
00814  * nssCKFWObject_GetObjectSize
00815  *
00816  */
00817 NSS_IMPLEMENT CK_ULONG
00818 nssCKFWObject_GetObjectSize
00819 (
00820   NSSCKFWObject *fwObject,
00821   CK_RV *pError
00822 )
00823 {
00824   CK_ULONG rv;
00825 
00826 #ifdef NSSDEBUG
00827   if( (CK_RV *)NULL == pError ) {
00828     return (CK_ULONG)0;
00829   }
00830 
00831   *pError = nssCKFWObject_verifyPointer(fwObject);
00832   if( CKR_OK != *pError ) {
00833     return (CK_ULONG)0;
00834   }
00835 #endif /* NSSDEBUG */
00836 
00837   if( (void *)NULL == (void *)fwObject->mdObject->GetObjectSize ) {
00838     *pError = CKR_INFORMATION_SENSITIVE;
00839     return (CK_ULONG)0;
00840   }
00841 
00842   *pError = nssCKFWMutex_Lock(fwObject->mutex);
00843   if( CKR_OK != *pError ) {
00844     return (CK_ULONG)0;
00845   }
00846 
00847   rv = fwObject->mdObject->GetObjectSize(fwObject->mdObject, fwObject,
00848     fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, 
00849     fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
00850     pError);
00851 
00852   (void)nssCKFWMutex_Unlock(fwObject->mutex);
00853   return rv;
00854 }
00855 
00856 /*
00857  * NSSCKFWObject_GetMDObject
00858  *
00859  */
00860 NSS_IMPLEMENT NSSCKMDObject *
00861 NSSCKFWObject_GetMDObject
00862 (
00863   NSSCKFWObject *fwObject
00864 )
00865 {
00866 #ifdef DEBUG
00867   if( CKR_OK != nssCKFWObject_verifyPointer(fwObject) ) {
00868     return (NSSCKMDObject *)NULL;
00869   }
00870 #endif /* DEBUG */
00871 
00872   return nssCKFWObject_GetMDObject(fwObject);
00873 }
00874 
00875 /*
00876  * NSSCKFWObject_GetArena
00877  *
00878  */
00879 NSS_IMPLEMENT NSSArena *
00880 NSSCKFWObject_GetArena
00881 (
00882   NSSCKFWObject *fwObject,
00883   CK_RV *pError
00884 )
00885 {
00886 #ifdef DEBUG
00887   if( (CK_RV *)NULL == pError ) {
00888     return (NSSArena *)NULL;
00889   }
00890 
00891   *pError = nssCKFWObject_verifyPointer(fwObject);
00892   if( CKR_OK != *pError ) {
00893     return (NSSArena *)NULL;
00894   }
00895 #endif /* DEBUG */
00896 
00897   return nssCKFWObject_GetArena(fwObject, pError);
00898 }
00899 
00900 /*
00901  * NSSCKFWObject_IsTokenObject
00902  *
00903  */
00904 NSS_IMPLEMENT CK_BBOOL
00905 NSSCKFWObject_IsTokenObject
00906 (
00907   NSSCKFWObject *fwObject
00908 )
00909 {
00910 #ifdef DEBUG
00911   if( CKR_OK != nssCKFWObject_verifyPointer(fwObject) ) {
00912     return CK_FALSE;
00913   }
00914 #endif /* DEBUG */
00915 
00916   return nssCKFWObject_IsTokenObject(fwObject);
00917 }
00918 
00919 /*
00920  * NSSCKFWObject_GetAttributeCount
00921  *
00922  */
00923 NSS_IMPLEMENT CK_ULONG
00924 NSSCKFWObject_GetAttributeCount
00925 (
00926   NSSCKFWObject *fwObject,
00927   CK_RV *pError
00928 )
00929 {
00930 #ifdef DEBUG
00931   if( (CK_RV *)NULL == pError ) {
00932     return (CK_ULONG)0;
00933   }
00934 
00935   *pError = nssCKFWObject_verifyPointer(fwObject);
00936   if( CKR_OK != *pError ) {
00937     return (CK_ULONG)0;
00938   }
00939 #endif /* DEBUG */
00940 
00941   return nssCKFWObject_GetAttributeCount(fwObject, pError);
00942 }
00943 
00944 /*
00945  * NSSCKFWObject_GetAttributeTypes
00946  *
00947  */
00948 NSS_IMPLEMENT CK_RV
00949 NSSCKFWObject_GetAttributeTypes
00950 (
00951   NSSCKFWObject *fwObject,
00952   CK_ATTRIBUTE_TYPE_PTR typeArray,
00953   CK_ULONG ulCount
00954 )
00955 {
00956 #ifdef DEBUG
00957   CK_RV error = CKR_OK;
00958 
00959   error = nssCKFWObject_verifyPointer(fwObject);
00960   if( CKR_OK != error ) {
00961     return error;
00962   }
00963 
00964   if( (CK_ATTRIBUTE_TYPE_PTR)NULL == typeArray ) {
00965     return CKR_ARGUMENTS_BAD;
00966   }
00967 #endif /* DEBUG */
00968 
00969   return nssCKFWObject_GetAttributeTypes(fwObject, typeArray, ulCount);
00970 }
00971 
00972 /*
00973  * NSSCKFWObject_GetAttributeSize
00974  *
00975  */
00976 NSS_IMPLEMENT CK_ULONG
00977 NSSCKFWObject_GetAttributeSize
00978 (
00979   NSSCKFWObject *fwObject,
00980   CK_ATTRIBUTE_TYPE attribute,
00981   CK_RV *pError
00982 )
00983 {
00984 #ifdef DEBUG
00985   if( (CK_RV *)NULL == pError ) {
00986     return (CK_ULONG)0;
00987   }
00988 
00989   *pError = nssCKFWObject_verifyPointer(fwObject);
00990   if( CKR_OK != *pError ) {
00991     return (CK_ULONG)0;
00992   }
00993 #endif /* DEBUG */
00994 
00995   return nssCKFWObject_GetAttributeSize(fwObject, attribute, pError);
00996 }
00997 
00998 /*
00999  * NSSCKFWObject_GetAttribute
01000  *
01001  */
01002 NSS_IMPLEMENT NSSItem *
01003 NSSCKFWObject_GetAttribute
01004 (
01005   NSSCKFWObject *fwObject,
01006   CK_ATTRIBUTE_TYPE attribute,
01007   NSSItem *itemOpt,
01008   NSSArena *arenaOpt,
01009   CK_RV *pError
01010 )
01011 {
01012 #ifdef DEBUG
01013   if( (CK_RV *)NULL == pError ) {
01014     return (NSSItem *)NULL;
01015   }
01016 
01017   *pError = nssCKFWObject_verifyPointer(fwObject);
01018   if( CKR_OK != *pError ) {
01019     return (NSSItem *)NULL;
01020   }
01021 #endif /* DEBUG */
01022 
01023   return nssCKFWObject_GetAttribute(fwObject, attribute, itemOpt, arenaOpt, pError);
01024 }
01025 
01026 /*
01027  * NSSCKFWObject_GetObjectSize
01028  *
01029  */
01030 NSS_IMPLEMENT CK_ULONG
01031 NSSCKFWObject_GetObjectSize
01032 (
01033   NSSCKFWObject *fwObject,
01034   CK_RV *pError
01035 )
01036 {
01037 #ifdef DEBUG
01038   if( (CK_RV *)NULL == pError ) {
01039     return (CK_ULONG)0;
01040   }
01041 
01042   *pError = nssCKFWObject_verifyPointer(fwObject);
01043   if( CKR_OK != *pError ) {
01044     return (CK_ULONG)0;
01045   }
01046 #endif /* DEBUG */
01047 
01048   return nssCKFWObject_GetObjectSize(fwObject, pError);
01049 }