/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * object.c * * This file implements the NSSCKFWObject type and methods. */ #ifndef CK_T #include "ck.h" #endif /* CK_T */ /* * NSSCKFWObject * * -- create/destroy -- * nssCKFWObject_Create * nssCKFWObject_Finalize * nssCKFWObject_Destroy * * -- public accessors -- * NSSCKFWObject_GetMDObject * NSSCKFWObject_GetArena * NSSCKFWObject_IsTokenObject * NSSCKFWObject_GetAttributeCount * NSSCKFWObject_GetAttributeTypes * NSSCKFWObject_GetAttributeSize * NSSCKFWObject_GetAttribute * NSSCKFWObject_SetAttribute * NSSCKFWObject_GetObjectSize * * -- implement public accessors -- * nssCKFWObject_GetMDObject * nssCKFWObject_GetArena * * -- private accessors -- * nssCKFWObject_SetHandle * nssCKFWObject_GetHandle * * -- module fronts -- * nssCKFWObject_IsTokenObject * nssCKFWObject_GetAttributeCount * nssCKFWObject_GetAttributeTypes * nssCKFWObject_GetAttributeSize * nssCKFWObject_GetAttribute * nssCKFWObject_SetAttribute * nssCKFWObject_GetObjectSize */ struct NSSCKFWObjectStr { NSSCKFWMutex *mutex; /* merely to serialise the MDObject calls */ NSSArena *arena; NSSArena *localArena; NSSCKMDObject *mdObject; NSSCKMDSession *mdSession; NSSCKFWSession *fwSession; NSSCKMDToken *mdToken; NSSCKFWToken *fwToken; NSSCKMDInstance *mdInstance; NSSCKFWInstance *fwInstance; CK_OBJECT_HANDLE hObject; }; #ifdef DEBUG /* * But first, the pointer-tracking stuff. * * NOTE: the pointer-tracking support in NSS/base currently relies * upon NSPR's CallOnce support. That, however, relies upon NSPR's * locking, which is tied into the runtime. We need a pointer-tracker * implementation that uses the locks supplied through C_Initialize. * That support, however, can be filled in later. So for now, I'll * just do this routines as no-ops. */ static CK_RV object_add_pointer( const NSSCKFWObject *fwObject) { return CKR_OK; } static CK_RV object_remove_pointer( const NSSCKFWObject *fwObject) { return CKR_OK; } NSS_IMPLEMENT CK_RV nssCKFWObject_verifyPointer( const NSSCKFWObject *fwObject) { return CKR_OK; } #endif /* DEBUG */ /* * nssCKFWObject_Create * */ NSS_IMPLEMENT NSSCKFWObject * nssCKFWObject_Create( NSSArena *arena, NSSCKMDObject *mdObject, NSSCKFWSession *fwSession, NSSCKFWToken *fwToken, NSSCKFWInstance *fwInstance, CK_RV *pError) { NSSArena *objArena = arena; NSSArena *localArena = NULL; NSSCKFWObject *fwObject; nssCKFWHash *mdObjectHash; #ifdef NSSDEBUG if (!pError) { return (NSSCKFWObject *)NULL; } if (PR_SUCCESS != nssArena_verifyPointer(arena)) { *pError = CKR_ARGUMENTS_BAD; return (NSSCKFWObject *)NULL; } #endif /* NSSDEBUG */ if (!fwToken) { *pError = CKR_ARGUMENTS_BAD; return (NSSCKFWObject *)NULL; } mdObjectHash = nssCKFWToken_GetMDObjectHash(fwToken); if (!mdObjectHash) { *pError = CKR_GENERAL_ERROR; return (NSSCKFWObject *)NULL; } if (nssCKFWHash_Exists(mdObjectHash, mdObject)) { fwObject = nssCKFWHash_Lookup(mdObjectHash, mdObject); return fwObject; } /* session objects should have their own arena so they can be destroyed in the end. */ if (arena == NULL) { localArena = objArena = NSSArena_Create(); if (objArena == NULL) { *pError = CKR_HOST_MEMORY; return (NSSCKFWObject *)NULL; } } fwObject = nss_ZNEW(objArena, NSSCKFWObject); if (!fwObject) { *pError = CKR_HOST_MEMORY; return (NSSCKFWObject *)NULL; } fwObject->arena = objArena; fwObject->localArena = localArena; fwObject->mdObject = mdObject; fwObject->fwSession = fwSession; if (fwSession) { fwObject->mdSession = nssCKFWSession_GetMDSession(fwSession); } fwObject->fwToken = fwToken; fwObject->mdToken = nssCKFWToken_GetMDToken(fwToken); fwObject->fwInstance = fwInstance; fwObject->mdInstance = nssCKFWInstance_GetMDInstance(fwInstance); fwObject->mutex = nssCKFWInstance_CreateMutex(fwInstance, objArena, pError); if (!fwObject->mutex) { if (CKR_OK == *pError) { *pError = CKR_GENERAL_ERROR; } nss_ZFreeIf(fwObject); if (localArena) { NSSArena_Destroy(localArena); } return (NSSCKFWObject *)NULL; } *pError = nssCKFWHash_Add(mdObjectHash, mdObject, fwObject); if (CKR_OK != *pError) { nss_ZFreeIf(fwObject); if (localArena) { NSSArena_Destroy(localArena); } return (NSSCKFWObject *)NULL; } #ifdef DEBUG *pError = object_add_pointer(fwObject); if (CKR_OK != *pError) { nssCKFWHash_Remove(mdObjectHash, mdObject); nss_ZFreeIf(fwObject); if (localArena) { NSSArena_Destroy(localArena); } return (NSSCKFWObject *)NULL; } #endif /* DEBUG */ *pError = CKR_OK; return fwObject; } /* * nssCKFWObject_Finalize * */ NSS_IMPLEMENT void nssCKFWObject_Finalize( NSSCKFWObject *fwObject, PRBool removeFromHash) { nssCKFWHash *mdObjectHash; NSSArena *arena = NULL; #ifdef NSSDEBUG if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) { return; } #endif /* NSSDEBUG */ (void)nssCKFWMutex_Destroy(fwObject->mutex); if (fwObject->mdObject->Finalize) { fwObject->mdObject->Finalize(fwObject->mdObject, fwObject, fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance); } if (removeFromHash) { mdObjectHash = nssCKFWToken_GetMDObjectHash(fwObject->fwToken); if (mdObjectHash) { nssCKFWHash_Remove(mdObjectHash, fwObject->mdObject); } } if (fwObject->fwSession) { nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject); } arena = fwObject->localArena; nss_ZFreeIf(fwObject); if (arena) { NSSArena_Destroy(arena); } #ifdef DEBUG (void)object_remove_pointer(fwObject); #endif /* DEBUG */ return; } /* * nssCKFWObject_Destroy * */ NSS_IMPLEMENT void nssCKFWObject_Destroy( NSSCKFWObject *fwObject) { nssCKFWHash *mdObjectHash; NSSArena *arena = NULL; #ifdef NSSDEBUG if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) { return; } #endif /* NSSDEBUG */ (void)nssCKFWMutex_Destroy(fwObject->mutex); if (fwObject->mdObject->Destroy) { fwObject->mdObject->Destroy(fwObject->mdObject, fwObject, fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance); } mdObjectHash = nssCKFWToken_GetMDObjectHash(fwObject->fwToken); if (mdObjectHash) { nssCKFWHash_Remove(mdObjectHash, fwObject->mdObject); } if (fwObject->fwSession) { nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject); } arena = fwObject->localArena; nss_ZFreeIf(fwObject); if (arena) { NSSArena_Destroy(arena); } #ifdef DEBUG (void)object_remove_pointer(fwObject); #endif /* DEBUG */ return; } /* * nssCKFWObject_GetMDObject * */ NSS_IMPLEMENT NSSCKMDObject * nssCKFWObject_GetMDObject( NSSCKFWObject *fwObject) { #ifdef NSSDEBUG if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) { return (NSSCKMDObject *)NULL; } #endif /* NSSDEBUG */ return fwObject->mdObject; } /* * nssCKFWObject_GetArena * */ NSS_IMPLEMENT NSSArena * nssCKFWObject_GetArena( NSSCKFWObject *fwObject, CK_RV *pError) { #ifdef NSSDEBUG if (!pError) { return (NSSArena *)NULL; } *pError = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != *pError) { return (NSSArena *)NULL; } #endif /* NSSDEBUG */ return fwObject->arena; } /* * nssCKFWObject_SetHandle * */ NSS_IMPLEMENT CK_RV nssCKFWObject_SetHandle( NSSCKFWObject *fwObject, CK_OBJECT_HANDLE hObject) { #ifdef NSSDEBUG CK_RV error = CKR_OK; #endif /* NSSDEBUG */ #ifdef NSSDEBUG error = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != error) { return error; } #endif /* NSSDEBUG */ if ((CK_OBJECT_HANDLE)0 != fwObject->hObject) { return CKR_GENERAL_ERROR; } fwObject->hObject = hObject; return CKR_OK; } /* * nssCKFWObject_GetHandle * */ NSS_IMPLEMENT CK_OBJECT_HANDLE nssCKFWObject_GetHandle( NSSCKFWObject *fwObject) { #ifdef NSSDEBUG if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) { return (CK_OBJECT_HANDLE)0; } #endif /* NSSDEBUG */ return fwObject->hObject; } /* * nssCKFWObject_IsTokenObject * */ NSS_IMPLEMENT CK_BBOOL nssCKFWObject_IsTokenObject( NSSCKFWObject *fwObject) { CK_BBOOL b = CK_FALSE; #ifdef NSSDEBUG if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) { return CK_FALSE; } #endif /* NSSDEBUG */ if (!fwObject->mdObject->IsTokenObject) { NSSItem item; NSSItem *pItem; CK_RV rv = CKR_OK; item.data = (void *)&b; item.size = sizeof(b); pItem = nssCKFWObject_GetAttribute(fwObject, CKA_TOKEN, &item, (NSSArena *)NULL, &rv); if (!pItem) { /* Error of some type */ b = CK_FALSE; goto done; } goto done; } b = fwObject->mdObject->IsTokenObject(fwObject->mdObject, fwObject, fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance); done: return b; } /* * nssCKFWObject_GetAttributeCount * */ NSS_IMPLEMENT CK_ULONG nssCKFWObject_GetAttributeCount( NSSCKFWObject *fwObject, CK_RV *pError) { CK_ULONG rv; #ifdef NSSDEBUG if (!pError) { return (CK_ULONG)0; } *pError = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != *pError) { return (CK_ULONG)0; } #endif /* NSSDEBUG */ if (!fwObject->mdObject->GetAttributeCount) { *pError = CKR_GENERAL_ERROR; return (CK_ULONG)0; } *pError = nssCKFWMutex_Lock(fwObject->mutex); if (CKR_OK != *pError) { return (CK_ULONG)0; } rv = fwObject->mdObject->GetAttributeCount(fwObject->mdObject, fwObject, fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance, pError); (void)nssCKFWMutex_Unlock(fwObject->mutex); return rv; } /* * nssCKFWObject_GetAttributeTypes * */ NSS_IMPLEMENT CK_RV nssCKFWObject_GetAttributeTypes( NSSCKFWObject *fwObject, CK_ATTRIBUTE_TYPE_PTR typeArray, CK_ULONG ulCount) { CK_RV error = CKR_OK; #ifdef NSSDEBUG error = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != error) { return error; } if ((CK_ATTRIBUTE_TYPE_PTR)NULL == typeArray) { return CKR_ARGUMENTS_BAD; } #endif /* NSSDEBUG */ if (!fwObject->mdObject->GetAttributeTypes) { return CKR_GENERAL_ERROR; } error = nssCKFWMutex_Lock(fwObject->mutex); if (CKR_OK != error) { return error; } error = fwObject->mdObject->GetAttributeTypes(fwObject->mdObject, fwObject, fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance, typeArray, ulCount); (void)nssCKFWMutex_Unlock(fwObject->mutex); return error; } /* * nssCKFWObject_GetAttributeSize * */ NSS_IMPLEMENT CK_ULONG nssCKFWObject_GetAttributeSize( NSSCKFWObject *fwObject, CK_ATTRIBUTE_TYPE attribute, CK_RV *pError) { CK_ULONG rv; if (!pError) { return (CK_ULONG)0; } if (!fwObject || !fwObject->mdObject || !fwObject->mdObject->GetAttributeSize) { *pError = CKR_GENERAL_ERROR; return (CK_ULONG)0; } *pError = nssCKFWMutex_Lock(fwObject->mutex); if (CKR_OK != *pError) { return (CK_ULONG)0; } rv = fwObject->mdObject->GetAttributeSize(fwObject->mdObject, fwObject, fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance, attribute, pError); (void)nssCKFWMutex_Unlock(fwObject->mutex); return rv; } /* * nssCKFWObject_GetAttribute * * Usual NSS allocation rules: * If itemOpt is not NULL, it will be returned; otherwise an NSSItem * will be allocated. If itemOpt is not NULL but itemOpt->data is, * the buffer will be allocated; otherwise, the buffer will be used. * Any allocations will come from the optional arena, if one is * specified. */ NSS_IMPLEMENT NSSItem * nssCKFWObject_GetAttribute( NSSCKFWObject *fwObject, CK_ATTRIBUTE_TYPE attribute, NSSItem *itemOpt, NSSArena *arenaOpt, CK_RV *pError) { NSSItem *rv = (NSSItem *)NULL; NSSCKFWItem mdItem; #ifdef NSSDEBUG if (!pError) { return (NSSItem *)NULL; } *pError = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != *pError) { return (NSSItem *)NULL; } #endif /* NSSDEBUG */ if (!fwObject->mdObject->GetAttribute) { *pError = CKR_GENERAL_ERROR; return (NSSItem *)NULL; } *pError = nssCKFWMutex_Lock(fwObject->mutex); if (CKR_OK != *pError) { return (NSSItem *)NULL; } mdItem = fwObject->mdObject->GetAttribute(fwObject->mdObject, fwObject, fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance, attribute, pError); if (!mdItem.item) { if (CKR_OK == *pError) { *pError = CKR_GENERAL_ERROR; } goto done; } if (!itemOpt) { rv = nss_ZNEW(arenaOpt, NSSItem); if (!rv) { *pError = CKR_HOST_MEMORY; goto done; } } else { rv = itemOpt; } if (!rv->data) { rv->size = mdItem.item->size; rv->data = nss_ZAlloc(arenaOpt, rv->size); if (!rv->data) { *pError = CKR_HOST_MEMORY; if (!itemOpt) { nss_ZFreeIf(rv); } rv = (NSSItem *)NULL; goto done; } } else { if (rv->size >= mdItem.item->size) { rv->size = mdItem.item->size; } else { *pError = CKR_BUFFER_TOO_SMALL; /* Should we set rv->size to mdItem->size? */ /* rv can't have been allocated */ rv = (NSSItem *)NULL; goto done; } } (void)nsslibc_memcpy(rv->data, mdItem.item->data, rv->size); if (PR_TRUE == mdItem.needsFreeing) { PR_ASSERT(fwObject->mdObject->FreeAttribute); if (fwObject->mdObject->FreeAttribute) { *pError = fwObject->mdObject->FreeAttribute(&mdItem); } } done: (void)nssCKFWMutex_Unlock(fwObject->mutex); return rv; } /* * nssCKFWObject_SetAttribute * */ NSS_IMPLEMENT CK_RV nssCKFWObject_SetAttribute( NSSCKFWObject *fwObject, NSSCKFWSession *fwSession, CK_ATTRIBUTE_TYPE attribute, NSSItem *value) { CK_RV error = CKR_OK; #ifdef NSSDEBUG error = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != error) { return error; } #endif /* NSSDEBUG */ if (CKA_TOKEN == attribute) { /* * We're changing from a session object to a token object or * vice-versa. */ CK_ATTRIBUTE a; NSSCKFWObject *newFwObject; NSSCKFWObject swab; a.type = CKA_TOKEN; a.pValue = value->data; a.ulValueLen = value->size; newFwObject = nssCKFWSession_CopyObject(fwSession, fwObject, &a, 1, &error); if (!newFwObject) { if (CKR_OK == error) { error = CKR_GENERAL_ERROR; } return error; } /* * Actually, I bet the locking is worse than this.. this part of * the code could probably use some scrutiny and reworking. */ error = nssCKFWMutex_Lock(fwObject->mutex); if (CKR_OK != error) { nssCKFWObject_Destroy(newFwObject); return error; } error = nssCKFWMutex_Lock(newFwObject->mutex); if (CKR_OK != error) { nssCKFWMutex_Unlock(fwObject->mutex); nssCKFWObject_Destroy(newFwObject); return error; } /* * Now, we have our new object, but it has a new fwObject pointer, * while we have to keep the existing one. So quick swap the contents. */ swab = *fwObject; *fwObject = *newFwObject; *newFwObject = swab; /* But keep the mutexes the same */ swab.mutex = fwObject->mutex; fwObject->mutex = newFwObject->mutex; newFwObject->mutex = swab.mutex; (void)nssCKFWMutex_Unlock(newFwObject->mutex); (void)nssCKFWMutex_Unlock(fwObject->mutex); /* * Either remove or add this to the list of session objects */ if (CK_FALSE == *(CK_BBOOL *)value->data) { /* * New one is a session object, except since we "stole" the fwObject, it's * not in the list. Add it. */ nssCKFWSession_RegisterSessionObject(fwSession, fwObject); } else { /* * New one is a token object, except since we "stole" the fwObject, it's * in the list. Remove it. */ if (fwObject->fwSession) { nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject); } } /* * Now delete the old object. Remember the names have changed. */ nssCKFWObject_Destroy(newFwObject); return CKR_OK; } else { /* * An "ordinary" change. */ if (!fwObject->mdObject->SetAttribute) { /* We could fake it with copying, like above.. later */ return CKR_ATTRIBUTE_READ_ONLY; } error = nssCKFWMutex_Lock(fwObject->mutex); if (CKR_OK != error) { return error; } error = fwObject->mdObject->SetAttribute(fwObject->mdObject, fwObject, fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance, attribute, value); (void)nssCKFWMutex_Unlock(fwObject->mutex); return error; } } /* * nssCKFWObject_GetObjectSize * */ NSS_IMPLEMENT CK_ULONG nssCKFWObject_GetObjectSize( NSSCKFWObject *fwObject, CK_RV *pError) { CK_ULONG rv; #ifdef NSSDEBUG if (!pError) { return (CK_ULONG)0; } *pError = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != *pError) { return (CK_ULONG)0; } #endif /* NSSDEBUG */ if (!fwObject->mdObject->GetObjectSize) { *pError = CKR_INFORMATION_SENSITIVE; return (CK_ULONG)0; } *pError = nssCKFWMutex_Lock(fwObject->mutex); if (CKR_OK != *pError) { return (CK_ULONG)0; } rv = fwObject->mdObject->GetObjectSize(fwObject->mdObject, fwObject, fwObject->mdSession, fwObject->fwSession, fwObject->mdToken, fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance, pError); (void)nssCKFWMutex_Unlock(fwObject->mutex); return rv; } /* * NSSCKFWObject_GetMDObject * */ NSS_IMPLEMENT NSSCKMDObject * NSSCKFWObject_GetMDObject( NSSCKFWObject *fwObject) { #ifdef DEBUG if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) { return (NSSCKMDObject *)NULL; } #endif /* DEBUG */ return nssCKFWObject_GetMDObject(fwObject); } /* * NSSCKFWObject_GetArena * */ NSS_IMPLEMENT NSSArena * NSSCKFWObject_GetArena( NSSCKFWObject *fwObject, CK_RV *pError) { #ifdef DEBUG if (!pError) { return (NSSArena *)NULL; } *pError = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != *pError) { return (NSSArena *)NULL; } #endif /* DEBUG */ return nssCKFWObject_GetArena(fwObject, pError); } /* * NSSCKFWObject_IsTokenObject * */ NSS_IMPLEMENT CK_BBOOL NSSCKFWObject_IsTokenObject( NSSCKFWObject *fwObject) { #ifdef DEBUG if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) { return CK_FALSE; } #endif /* DEBUG */ return nssCKFWObject_IsTokenObject(fwObject); } /* * NSSCKFWObject_GetAttributeCount * */ NSS_IMPLEMENT CK_ULONG NSSCKFWObject_GetAttributeCount( NSSCKFWObject *fwObject, CK_RV *pError) { #ifdef DEBUG if (!pError) { return (CK_ULONG)0; } *pError = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != *pError) { return (CK_ULONG)0; } #endif /* DEBUG */ return nssCKFWObject_GetAttributeCount(fwObject, pError); } /* * NSSCKFWObject_GetAttributeTypes * */ NSS_IMPLEMENT CK_RV NSSCKFWObject_GetAttributeTypes( NSSCKFWObject *fwObject, CK_ATTRIBUTE_TYPE_PTR typeArray, CK_ULONG ulCount) { #ifdef DEBUG CK_RV error = CKR_OK; error = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != error) { return error; } if ((CK_ATTRIBUTE_TYPE_PTR)NULL == typeArray) { return CKR_ARGUMENTS_BAD; } #endif /* DEBUG */ return nssCKFWObject_GetAttributeTypes(fwObject, typeArray, ulCount); } /* * NSSCKFWObject_GetAttributeSize * */ NSS_IMPLEMENT CK_ULONG NSSCKFWObject_GetAttributeSize( NSSCKFWObject *fwObject, CK_ATTRIBUTE_TYPE attribute, CK_RV *pError) { #ifdef DEBUG if (!pError) { return (CK_ULONG)0; } *pError = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != *pError) { return (CK_ULONG)0; } #endif /* DEBUG */ return nssCKFWObject_GetAttributeSize(fwObject, attribute, pError); } /* * NSSCKFWObject_GetAttribute * */ NSS_IMPLEMENT NSSItem * NSSCKFWObject_GetAttribute( NSSCKFWObject *fwObject, CK_ATTRIBUTE_TYPE attribute, NSSItem *itemOpt, NSSArena *arenaOpt, CK_RV *pError) { #ifdef DEBUG if (!pError) { return (NSSItem *)NULL; } *pError = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != *pError) { return (NSSItem *)NULL; } #endif /* DEBUG */ return nssCKFWObject_GetAttribute(fwObject, attribute, itemOpt, arenaOpt, pError); } /* * NSSCKFWObject_GetObjectSize * */ NSS_IMPLEMENT CK_ULONG NSSCKFWObject_GetObjectSize( NSSCKFWObject *fwObject, CK_RV *pError) { #ifdef DEBUG if (!pError) { return (CK_ULONG)0; } *pError = nssCKFWObject_verifyPointer(fwObject); if (CKR_OK != *pError) { return (CK_ULONG)0; } #endif /* DEBUG */ return nssCKFWObject_GetObjectSize(fwObject, pError); }