1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 /*
6  * object.c
7  *
8  * This file implements the NSSCKFWObject type and methods.
9  */
10 
11 #ifndef CK_T
12 #include "ck.h"
13 #endif /* CK_T */
14 
15 /*
16  * NSSCKFWObject
17  *
18  * -- create/destroy --
19  *  nssCKFWObject_Create
20  *  nssCKFWObject_Finalize
21  *  nssCKFWObject_Destroy
22  *
23  * -- public accessors --
24  *  NSSCKFWObject_GetMDObject
25  *  NSSCKFWObject_GetArena
26  *  NSSCKFWObject_IsTokenObject
27  *  NSSCKFWObject_GetAttributeCount
28  *  NSSCKFWObject_GetAttributeTypes
29  *  NSSCKFWObject_GetAttributeSize
30  *  NSSCKFWObject_GetAttribute
31  *  NSSCKFWObject_SetAttribute
32  *  NSSCKFWObject_GetObjectSize
33  *
34  * -- implement public accessors --
35  *  nssCKFWObject_GetMDObject
36  *  nssCKFWObject_GetArena
37  *
38  * -- private accessors --
39  *  nssCKFWObject_SetHandle
40  *  nssCKFWObject_GetHandle
41  *
42  * -- module fronts --
43  *  nssCKFWObject_IsTokenObject
44  *  nssCKFWObject_GetAttributeCount
45  *  nssCKFWObject_GetAttributeTypes
46  *  nssCKFWObject_GetAttributeSize
47  *  nssCKFWObject_GetAttribute
48  *  nssCKFWObject_SetAttribute
49  *  nssCKFWObject_GetObjectSize
50  */
51 
52 struct NSSCKFWObjectStr {
53     NSSCKFWMutex *mutex; /* merely to serialise the MDObject calls */
54     NSSArena *arena;
55     NSSCKMDObject *mdObject;
56     NSSCKMDSession *mdSession;
57     NSSCKFWSession *fwSession;
58     NSSCKMDToken *mdToken;
59     NSSCKFWToken *fwToken;
60     NSSCKMDInstance *mdInstance;
61     NSSCKFWInstance *fwInstance;
62     CK_OBJECT_HANDLE hObject;
63 };
64 
65 #ifdef DEBUG
66 /*
67  * But first, the pointer-tracking stuff.
68  *
69  * NOTE: the pointer-tracking support in NSS/base currently relies
70  * upon NSPR's CallOnce support.  That, however, relies upon NSPR's
71  * locking, which is tied into the runtime.  We need a pointer-tracker
72  * implementation that uses the locks supplied through C_Initialize.
73  * That support, however, can be filled in later.  So for now, I'll
74  * just do this routines as no-ops.
75  */
76 
77 static CK_RV
object_add_pointer(const NSSCKFWObject * fwObject)78 object_add_pointer(
79     const NSSCKFWObject *fwObject)
80 {
81     return CKR_OK;
82 }
83 
84 static CK_RV
object_remove_pointer(const NSSCKFWObject * fwObject)85 object_remove_pointer(
86     const NSSCKFWObject *fwObject)
87 {
88     return CKR_OK;
89 }
90 
91 NSS_IMPLEMENT CK_RV
nssCKFWObject_verifyPointer(const NSSCKFWObject * fwObject)92 nssCKFWObject_verifyPointer(
93     const NSSCKFWObject *fwObject)
94 {
95     return CKR_OK;
96 }
97 
98 #endif /* DEBUG */
99 
100 /*
101  * nssCKFWObject_Create
102  *
103  */
104 NSS_IMPLEMENT NSSCKFWObject *
nssCKFWObject_Create(NSSArena * arena,NSSCKMDObject * mdObject,NSSCKFWSession * fwSession,NSSCKFWToken * fwToken,NSSCKFWInstance * fwInstance,CK_RV * pError)105 nssCKFWObject_Create(
106     NSSArena *arena,
107     NSSCKMDObject *mdObject,
108     NSSCKFWSession *fwSession,
109     NSSCKFWToken *fwToken,
110     NSSCKFWInstance *fwInstance,
111     CK_RV *pError)
112 {
113     NSSCKFWObject *fwObject;
114     nssCKFWHash *mdObjectHash;
115 
116 #ifdef NSSDEBUG
117     if (!pError) {
118         return (NSSCKFWObject *)NULL;
119     }
120 
121     if (PR_SUCCESS != nssArena_verifyPointer(arena)) {
122         *pError = CKR_ARGUMENTS_BAD;
123         return (NSSCKFWObject *)NULL;
124     }
125 #endif /* NSSDEBUG */
126 
127     if (!fwToken) {
128         *pError = CKR_ARGUMENTS_BAD;
129         return (NSSCKFWObject *)NULL;
130     }
131     mdObjectHash = nssCKFWToken_GetMDObjectHash(fwToken);
132     if (!mdObjectHash) {
133         *pError = CKR_GENERAL_ERROR;
134         return (NSSCKFWObject *)NULL;
135     }
136 
137     if (nssCKFWHash_Exists(mdObjectHash, mdObject)) {
138         fwObject = nssCKFWHash_Lookup(mdObjectHash, mdObject);
139         return fwObject;
140     }
141 
142     fwObject = nss_ZNEW(arena, NSSCKFWObject);
143     if (!fwObject) {
144         *pError = CKR_HOST_MEMORY;
145         return (NSSCKFWObject *)NULL;
146     }
147 
148     fwObject->arena = arena;
149     fwObject->mdObject = mdObject;
150     fwObject->fwSession = fwSession;
151 
152     if (fwSession) {
153         fwObject->mdSession = nssCKFWSession_GetMDSession(fwSession);
154     }
155 
156     fwObject->fwToken = fwToken;
157     fwObject->mdToken = nssCKFWToken_GetMDToken(fwToken);
158     fwObject->fwInstance = fwInstance;
159     fwObject->mdInstance = nssCKFWInstance_GetMDInstance(fwInstance);
160     fwObject->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError);
161     if (!fwObject->mutex) {
162         if (CKR_OK == *pError) {
163             *pError = CKR_GENERAL_ERROR;
164         }
165         nss_ZFreeIf(fwObject);
166         return (NSSCKFWObject *)NULL;
167     }
168 
169     *pError = nssCKFWHash_Add(mdObjectHash, mdObject, fwObject);
170     if (CKR_OK != *pError) {
171         nss_ZFreeIf(fwObject);
172         return (NSSCKFWObject *)NULL;
173     }
174 
175 #ifdef DEBUG
176     *pError = object_add_pointer(fwObject);
177     if (CKR_OK != *pError) {
178         nssCKFWHash_Remove(mdObjectHash, mdObject);
179         nss_ZFreeIf(fwObject);
180         return (NSSCKFWObject *)NULL;
181     }
182 #endif /* DEBUG */
183 
184     *pError = CKR_OK;
185     return fwObject;
186 }
187 
188 /*
189  * nssCKFWObject_Finalize
190  *
191  */
192 NSS_IMPLEMENT void
nssCKFWObject_Finalize(NSSCKFWObject * fwObject,PRBool removeFromHash)193 nssCKFWObject_Finalize(
194     NSSCKFWObject *fwObject,
195     PRBool removeFromHash)
196 {
197     nssCKFWHash *mdObjectHash;
198 
199 #ifdef NSSDEBUG
200     if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
201         return;
202     }
203 #endif /* NSSDEBUG */
204 
205     (void)nssCKFWMutex_Destroy(fwObject->mutex);
206 
207     if (fwObject->mdObject->Finalize) {
208         fwObject->mdObject->Finalize(fwObject->mdObject, fwObject,
209                                      fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
210                                      fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance);
211     }
212 
213     if (removeFromHash) {
214         mdObjectHash = nssCKFWToken_GetMDObjectHash(fwObject->fwToken);
215         if (mdObjectHash) {
216             nssCKFWHash_Remove(mdObjectHash, fwObject->mdObject);
217         }
218     }
219 
220     if (fwObject->fwSession) {
221         nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject);
222     }
223     nss_ZFreeIf(fwObject);
224 
225 #ifdef DEBUG
226     (void)object_remove_pointer(fwObject);
227 #endif /* DEBUG */
228 
229     return;
230 }
231 
232 /*
233  * nssCKFWObject_Destroy
234  *
235  */
236 NSS_IMPLEMENT void
nssCKFWObject_Destroy(NSSCKFWObject * fwObject)237 nssCKFWObject_Destroy(
238     NSSCKFWObject *fwObject)
239 {
240     nssCKFWHash *mdObjectHash;
241 
242 #ifdef NSSDEBUG
243     if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
244         return;
245     }
246 #endif /* NSSDEBUG */
247 
248     (void)nssCKFWMutex_Destroy(fwObject->mutex);
249 
250     if (fwObject->mdObject->Destroy) {
251         fwObject->mdObject->Destroy(fwObject->mdObject, fwObject,
252                                     fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
253                                     fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance);
254     }
255 
256     mdObjectHash = nssCKFWToken_GetMDObjectHash(fwObject->fwToken);
257     if (mdObjectHash) {
258         nssCKFWHash_Remove(mdObjectHash, fwObject->mdObject);
259     }
260 
261     if (fwObject->fwSession) {
262         nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject);
263     }
264     nss_ZFreeIf(fwObject);
265 
266 #ifdef DEBUG
267     (void)object_remove_pointer(fwObject);
268 #endif /* DEBUG */
269 
270     return;
271 }
272 
273 /*
274  * nssCKFWObject_GetMDObject
275  *
276  */
277 NSS_IMPLEMENT NSSCKMDObject *
nssCKFWObject_GetMDObject(NSSCKFWObject * fwObject)278 nssCKFWObject_GetMDObject(
279     NSSCKFWObject *fwObject)
280 {
281 #ifdef NSSDEBUG
282     if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
283         return (NSSCKMDObject *)NULL;
284     }
285 #endif /* NSSDEBUG */
286 
287     return fwObject->mdObject;
288 }
289 
290 /*
291  * nssCKFWObject_GetArena
292  *
293  */
294 NSS_IMPLEMENT NSSArena *
nssCKFWObject_GetArena(NSSCKFWObject * fwObject,CK_RV * pError)295 nssCKFWObject_GetArena(
296     NSSCKFWObject *fwObject,
297     CK_RV *pError)
298 {
299 #ifdef NSSDEBUG
300     if (!pError) {
301         return (NSSArena *)NULL;
302     }
303 
304     *pError = nssCKFWObject_verifyPointer(fwObject);
305     if (CKR_OK != *pError) {
306         return (NSSArena *)NULL;
307     }
308 #endif /* NSSDEBUG */
309 
310     return fwObject->arena;
311 }
312 
313 /*
314  * nssCKFWObject_SetHandle
315  *
316  */
317 NSS_IMPLEMENT CK_RV
nssCKFWObject_SetHandle(NSSCKFWObject * fwObject,CK_OBJECT_HANDLE hObject)318 nssCKFWObject_SetHandle(
319     NSSCKFWObject *fwObject,
320     CK_OBJECT_HANDLE hObject)
321 {
322 #ifdef NSSDEBUG
323     CK_RV error = CKR_OK;
324 #endif /* NSSDEBUG */
325 
326 #ifdef NSSDEBUG
327     error = nssCKFWObject_verifyPointer(fwObject);
328     if (CKR_OK != error) {
329         return error;
330     }
331 #endif /* NSSDEBUG */
332 
333     if ((CK_OBJECT_HANDLE)0 != fwObject->hObject) {
334         return CKR_GENERAL_ERROR;
335     }
336 
337     fwObject->hObject = hObject;
338 
339     return CKR_OK;
340 }
341 
342 /*
343  * nssCKFWObject_GetHandle
344  *
345  */
346 NSS_IMPLEMENT CK_OBJECT_HANDLE
nssCKFWObject_GetHandle(NSSCKFWObject * fwObject)347 nssCKFWObject_GetHandle(
348     NSSCKFWObject *fwObject)
349 {
350 #ifdef NSSDEBUG
351     if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
352         return (CK_OBJECT_HANDLE)0;
353     }
354 #endif /* NSSDEBUG */
355 
356     return fwObject->hObject;
357 }
358 
359 /*
360  * nssCKFWObject_IsTokenObject
361  *
362  */
363 NSS_IMPLEMENT CK_BBOOL
nssCKFWObject_IsTokenObject(NSSCKFWObject * fwObject)364 nssCKFWObject_IsTokenObject(
365     NSSCKFWObject *fwObject)
366 {
367     CK_BBOOL b = CK_FALSE;
368 
369 #ifdef NSSDEBUG
370     if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
371         return CK_FALSE;
372     }
373 #endif /* NSSDEBUG */
374 
375     if (!fwObject->mdObject->IsTokenObject) {
376         NSSItem item;
377         NSSItem *pItem;
378         CK_RV rv = CKR_OK;
379 
380         item.data = (void *)&b;
381         item.size = sizeof(b);
382 
383         pItem = nssCKFWObject_GetAttribute(fwObject, CKA_TOKEN, &item,
384                                            (NSSArena *)NULL, &rv);
385         if (!pItem) {
386             /* Error of some type */
387             b = CK_FALSE;
388             goto done;
389         }
390 
391         goto done;
392     }
393 
394     b = fwObject->mdObject->IsTokenObject(fwObject->mdObject, fwObject,
395                                           fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
396                                           fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance);
397 
398 done:
399     return b;
400 }
401 
402 /*
403  * nssCKFWObject_GetAttributeCount
404  *
405  */
406 NSS_IMPLEMENT CK_ULONG
nssCKFWObject_GetAttributeCount(NSSCKFWObject * fwObject,CK_RV * pError)407 nssCKFWObject_GetAttributeCount(
408     NSSCKFWObject *fwObject,
409     CK_RV *pError)
410 {
411     CK_ULONG rv;
412 
413 #ifdef NSSDEBUG
414     if (!pError) {
415         return (CK_ULONG)0;
416     }
417 
418     *pError = nssCKFWObject_verifyPointer(fwObject);
419     if (CKR_OK != *pError) {
420         return (CK_ULONG)0;
421     }
422 #endif /* NSSDEBUG */
423 
424     if (!fwObject->mdObject->GetAttributeCount) {
425         *pError = CKR_GENERAL_ERROR;
426         return (CK_ULONG)0;
427     }
428 
429     *pError = nssCKFWMutex_Lock(fwObject->mutex);
430     if (CKR_OK != *pError) {
431         return (CK_ULONG)0;
432     }
433 
434     rv = fwObject->mdObject->GetAttributeCount(fwObject->mdObject, fwObject,
435                                                fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
436                                                fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
437                                                pError);
438 
439     (void)nssCKFWMutex_Unlock(fwObject->mutex);
440     return rv;
441 }
442 
443 /*
444  * nssCKFWObject_GetAttributeTypes
445  *
446  */
447 NSS_IMPLEMENT CK_RV
nssCKFWObject_GetAttributeTypes(NSSCKFWObject * fwObject,CK_ATTRIBUTE_TYPE_PTR typeArray,CK_ULONG ulCount)448 nssCKFWObject_GetAttributeTypes(
449     NSSCKFWObject *fwObject,
450     CK_ATTRIBUTE_TYPE_PTR typeArray,
451     CK_ULONG ulCount)
452 {
453     CK_RV error = CKR_OK;
454 
455 #ifdef NSSDEBUG
456     error = nssCKFWObject_verifyPointer(fwObject);
457     if (CKR_OK != error) {
458         return error;
459     }
460 
461     if ((CK_ATTRIBUTE_TYPE_PTR)NULL == typeArray) {
462         return CKR_ARGUMENTS_BAD;
463     }
464 #endif /* NSSDEBUG */
465 
466     if (!fwObject->mdObject->GetAttributeTypes) {
467         return CKR_GENERAL_ERROR;
468     }
469 
470     error = nssCKFWMutex_Lock(fwObject->mutex);
471     if (CKR_OK != error) {
472         return error;
473     }
474 
475     error = fwObject->mdObject->GetAttributeTypes(fwObject->mdObject, fwObject,
476                                                   fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
477                                                   fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
478                                                   typeArray, ulCount);
479 
480     (void)nssCKFWMutex_Unlock(fwObject->mutex);
481     return error;
482 }
483 
484 /*
485  * nssCKFWObject_GetAttributeSize
486  *
487  */
488 NSS_IMPLEMENT CK_ULONG
nssCKFWObject_GetAttributeSize(NSSCKFWObject * fwObject,CK_ATTRIBUTE_TYPE attribute,CK_RV * pError)489 nssCKFWObject_GetAttributeSize(
490     NSSCKFWObject *fwObject,
491     CK_ATTRIBUTE_TYPE attribute,
492     CK_RV *pError)
493 {
494     CK_ULONG rv;
495 
496 #ifdef NSSDEBUG
497     if (!pError) {
498         return (CK_ULONG)0;
499     }
500 
501     *pError = nssCKFWObject_verifyPointer(fwObject);
502     if (CKR_OK != *pError) {
503         return (CK_ULONG)0;
504     }
505 #endif /* NSSDEBUG */
506 
507     if (!fwObject->mdObject->GetAttributeSize) {
508         *pError = CKR_GENERAL_ERROR;
509         return (CK_ULONG)0;
510     }
511 
512     *pError = nssCKFWMutex_Lock(fwObject->mutex);
513     if (CKR_OK != *pError) {
514         return (CK_ULONG)0;
515     }
516 
517     rv = fwObject->mdObject->GetAttributeSize(fwObject->mdObject, fwObject,
518                                               fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
519                                               fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
520                                               attribute, pError);
521 
522     (void)nssCKFWMutex_Unlock(fwObject->mutex);
523     return rv;
524 }
525 
526 /*
527  * nssCKFWObject_GetAttribute
528  *
529  * Usual NSS allocation rules:
530  * If itemOpt is not NULL, it will be returned; otherwise an NSSItem
531  * will be allocated.  If itemOpt is not NULL but itemOpt->data is,
532  * the buffer will be allocated; otherwise, the buffer will be used.
533  * Any allocations will come from the optional arena, if one is
534  * specified.
535  */
536 NSS_IMPLEMENT NSSItem *
nssCKFWObject_GetAttribute(NSSCKFWObject * fwObject,CK_ATTRIBUTE_TYPE attribute,NSSItem * itemOpt,NSSArena * arenaOpt,CK_RV * pError)537 nssCKFWObject_GetAttribute(
538     NSSCKFWObject *fwObject,
539     CK_ATTRIBUTE_TYPE attribute,
540     NSSItem *itemOpt,
541     NSSArena *arenaOpt,
542     CK_RV *pError)
543 {
544     NSSItem *rv = (NSSItem *)NULL;
545     NSSCKFWItem mdItem;
546 
547 #ifdef NSSDEBUG
548     if (!pError) {
549         return (NSSItem *)NULL;
550     }
551 
552     *pError = nssCKFWObject_verifyPointer(fwObject);
553     if (CKR_OK != *pError) {
554         return (NSSItem *)NULL;
555     }
556 #endif /* NSSDEBUG */
557 
558     if (!fwObject->mdObject->GetAttribute) {
559         *pError = CKR_GENERAL_ERROR;
560         return (NSSItem *)NULL;
561     }
562 
563     *pError = nssCKFWMutex_Lock(fwObject->mutex);
564     if (CKR_OK != *pError) {
565         return (NSSItem *)NULL;
566     }
567 
568     mdItem = fwObject->mdObject->GetAttribute(fwObject->mdObject, fwObject,
569                                               fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
570                                               fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
571                                               attribute, pError);
572 
573     if (!mdItem.item) {
574         if (CKR_OK == *pError) {
575             *pError = CKR_GENERAL_ERROR;
576         }
577 
578         goto done;
579     }
580 
581     if (!itemOpt) {
582         rv = nss_ZNEW(arenaOpt, NSSItem);
583         if (!rv) {
584             *pError = CKR_HOST_MEMORY;
585             goto done;
586         }
587     } else {
588         rv = itemOpt;
589     }
590 
591     if (!rv->data) {
592         rv->size = mdItem.item->size;
593         rv->data = nss_ZAlloc(arenaOpt, rv->size);
594         if (!rv->data) {
595             *pError = CKR_HOST_MEMORY;
596             if (!itemOpt) {
597                 nss_ZFreeIf(rv);
598             }
599             rv = (NSSItem *)NULL;
600             goto done;
601         }
602     } else {
603         if (rv->size >= mdItem.item->size) {
604             rv->size = mdItem.item->size;
605         } else {
606             *pError = CKR_BUFFER_TOO_SMALL;
607             /* Should we set rv->size to mdItem->size? */
608             /* rv can't have been allocated */
609             rv = (NSSItem *)NULL;
610             goto done;
611         }
612     }
613 
614     (void)nsslibc_memcpy(rv->data, mdItem.item->data, rv->size);
615 
616     if (PR_TRUE == mdItem.needsFreeing) {
617         PR_ASSERT(fwObject->mdObject->FreeAttribute);
618         if (fwObject->mdObject->FreeAttribute) {
619             *pError = fwObject->mdObject->FreeAttribute(&mdItem);
620         }
621     }
622 
623 done:
624     (void)nssCKFWMutex_Unlock(fwObject->mutex);
625     return rv;
626 }
627 
628 /*
629  * nssCKFWObject_SetAttribute
630  *
631  */
632 NSS_IMPLEMENT CK_RV
nssCKFWObject_SetAttribute(NSSCKFWObject * fwObject,NSSCKFWSession * fwSession,CK_ATTRIBUTE_TYPE attribute,NSSItem * value)633 nssCKFWObject_SetAttribute(
634     NSSCKFWObject *fwObject,
635     NSSCKFWSession *fwSession,
636     CK_ATTRIBUTE_TYPE attribute,
637     NSSItem *value)
638 {
639     CK_RV error = CKR_OK;
640 
641 #ifdef NSSDEBUG
642     error = nssCKFWObject_verifyPointer(fwObject);
643     if (CKR_OK != error) {
644         return error;
645     }
646 #endif /* NSSDEBUG */
647 
648     if (CKA_TOKEN == attribute) {
649         /*
650          * We're changing from a session object to a token object or
651          * vice-versa.
652          */
653 
654         CK_ATTRIBUTE a;
655         NSSCKFWObject *newFwObject;
656         NSSCKFWObject swab;
657 
658         a.type = CKA_TOKEN;
659         a.pValue = value->data;
660         a.ulValueLen = value->size;
661 
662         newFwObject = nssCKFWSession_CopyObject(fwSession, fwObject,
663                                                 &a, 1, &error);
664         if (!newFwObject) {
665             if (CKR_OK == error) {
666                 error = CKR_GENERAL_ERROR;
667             }
668             return error;
669         }
670 
671         /*
672          * Actually, I bet the locking is worse than this.. this part of
673          * the code could probably use some scrutiny and reworking.
674          */
675         error = nssCKFWMutex_Lock(fwObject->mutex);
676         if (CKR_OK != error) {
677             nssCKFWObject_Destroy(newFwObject);
678             return error;
679         }
680 
681         error = nssCKFWMutex_Lock(newFwObject->mutex);
682         if (CKR_OK != error) {
683             nssCKFWMutex_Unlock(fwObject->mutex);
684             nssCKFWObject_Destroy(newFwObject);
685             return error;
686         }
687 
688         /*
689          * Now, we have our new object, but it has a new fwObject pointer,
690          * while we have to keep the existing one.  So quick swap the contents.
691          */
692         swab = *fwObject;
693         *fwObject = *newFwObject;
694         *newFwObject = swab;
695 
696         /* But keep the mutexes the same */
697         swab.mutex = fwObject->mutex;
698         fwObject->mutex = newFwObject->mutex;
699         newFwObject->mutex = swab.mutex;
700 
701         (void)nssCKFWMutex_Unlock(newFwObject->mutex);
702         (void)nssCKFWMutex_Unlock(fwObject->mutex);
703 
704         /*
705          * Either remove or add this to the list of session objects
706          */
707 
708         if (CK_FALSE == *(CK_BBOOL *)value->data) {
709             /*
710              * New one is a session object, except since we "stole" the fwObject, it's
711              * not in the list.  Add it.
712              */
713             nssCKFWSession_RegisterSessionObject(fwSession, fwObject);
714         } else {
715             /*
716              * New one is a token object, except since we "stole" the fwObject, it's
717              * in the list.  Remove it.
718              */
719             if (fwObject->fwSession) {
720                 nssCKFWSession_DeregisterSessionObject(fwObject->fwSession, fwObject);
721             }
722         }
723 
724         /*
725          * Now delete the old object.  Remember the names have changed.
726          */
727         nssCKFWObject_Destroy(newFwObject);
728 
729         return CKR_OK;
730     } else {
731         /*
732          * An "ordinary" change.
733          */
734         if (!fwObject->mdObject->SetAttribute) {
735             /* We could fake it with copying, like above.. later */
736             return CKR_ATTRIBUTE_READ_ONLY;
737         }
738 
739         error = nssCKFWMutex_Lock(fwObject->mutex);
740         if (CKR_OK != error) {
741             return error;
742         }
743 
744         error = fwObject->mdObject->SetAttribute(fwObject->mdObject, fwObject,
745                                                  fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
746                                                  fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
747                                                  attribute, value);
748 
749         (void)nssCKFWMutex_Unlock(fwObject->mutex);
750 
751         return error;
752     }
753 }
754 
755 /*
756  * nssCKFWObject_GetObjectSize
757  *
758  */
759 NSS_IMPLEMENT CK_ULONG
nssCKFWObject_GetObjectSize(NSSCKFWObject * fwObject,CK_RV * pError)760 nssCKFWObject_GetObjectSize(
761     NSSCKFWObject *fwObject,
762     CK_RV *pError)
763 {
764     CK_ULONG rv;
765 
766 #ifdef NSSDEBUG
767     if (!pError) {
768         return (CK_ULONG)0;
769     }
770 
771     *pError = nssCKFWObject_verifyPointer(fwObject);
772     if (CKR_OK != *pError) {
773         return (CK_ULONG)0;
774     }
775 #endif /* NSSDEBUG */
776 
777     if (!fwObject->mdObject->GetObjectSize) {
778         *pError = CKR_INFORMATION_SENSITIVE;
779         return (CK_ULONG)0;
780     }
781 
782     *pError = nssCKFWMutex_Lock(fwObject->mutex);
783     if (CKR_OK != *pError) {
784         return (CK_ULONG)0;
785     }
786 
787     rv = fwObject->mdObject->GetObjectSize(fwObject->mdObject, fwObject,
788                                            fwObject->mdSession, fwObject->fwSession, fwObject->mdToken,
789                                            fwObject->fwToken, fwObject->mdInstance, fwObject->fwInstance,
790                                            pError);
791 
792     (void)nssCKFWMutex_Unlock(fwObject->mutex);
793     return rv;
794 }
795 
796 /*
797  * NSSCKFWObject_GetMDObject
798  *
799  */
800 NSS_IMPLEMENT NSSCKMDObject *
NSSCKFWObject_GetMDObject(NSSCKFWObject * fwObject)801 NSSCKFWObject_GetMDObject(
802     NSSCKFWObject *fwObject)
803 {
804 #ifdef DEBUG
805     if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
806         return (NSSCKMDObject *)NULL;
807     }
808 #endif /* DEBUG */
809 
810     return nssCKFWObject_GetMDObject(fwObject);
811 }
812 
813 /*
814  * NSSCKFWObject_GetArena
815  *
816  */
817 NSS_IMPLEMENT NSSArena *
NSSCKFWObject_GetArena(NSSCKFWObject * fwObject,CK_RV * pError)818 NSSCKFWObject_GetArena(
819     NSSCKFWObject *fwObject,
820     CK_RV *pError)
821 {
822 #ifdef DEBUG
823     if (!pError) {
824         return (NSSArena *)NULL;
825     }
826 
827     *pError = nssCKFWObject_verifyPointer(fwObject);
828     if (CKR_OK != *pError) {
829         return (NSSArena *)NULL;
830     }
831 #endif /* DEBUG */
832 
833     return nssCKFWObject_GetArena(fwObject, pError);
834 }
835 
836 /*
837  * NSSCKFWObject_IsTokenObject
838  *
839  */
840 NSS_IMPLEMENT CK_BBOOL
NSSCKFWObject_IsTokenObject(NSSCKFWObject * fwObject)841 NSSCKFWObject_IsTokenObject(
842     NSSCKFWObject *fwObject)
843 {
844 #ifdef DEBUG
845     if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
846         return CK_FALSE;
847     }
848 #endif /* DEBUG */
849 
850     return nssCKFWObject_IsTokenObject(fwObject);
851 }
852 
853 /*
854  * NSSCKFWObject_GetAttributeCount
855  *
856  */
857 NSS_IMPLEMENT CK_ULONG
NSSCKFWObject_GetAttributeCount(NSSCKFWObject * fwObject,CK_RV * pError)858 NSSCKFWObject_GetAttributeCount(
859     NSSCKFWObject *fwObject,
860     CK_RV *pError)
861 {
862 #ifdef DEBUG
863     if (!pError) {
864         return (CK_ULONG)0;
865     }
866 
867     *pError = nssCKFWObject_verifyPointer(fwObject);
868     if (CKR_OK != *pError) {
869         return (CK_ULONG)0;
870     }
871 #endif /* DEBUG */
872 
873     return nssCKFWObject_GetAttributeCount(fwObject, pError);
874 }
875 
876 /*
877  * NSSCKFWObject_GetAttributeTypes
878  *
879  */
880 NSS_IMPLEMENT CK_RV
NSSCKFWObject_GetAttributeTypes(NSSCKFWObject * fwObject,CK_ATTRIBUTE_TYPE_PTR typeArray,CK_ULONG ulCount)881 NSSCKFWObject_GetAttributeTypes(
882     NSSCKFWObject *fwObject,
883     CK_ATTRIBUTE_TYPE_PTR typeArray,
884     CK_ULONG ulCount)
885 {
886 #ifdef DEBUG
887     CK_RV error = CKR_OK;
888 
889     error = nssCKFWObject_verifyPointer(fwObject);
890     if (CKR_OK != error) {
891         return error;
892     }
893 
894     if ((CK_ATTRIBUTE_TYPE_PTR)NULL == typeArray) {
895         return CKR_ARGUMENTS_BAD;
896     }
897 #endif /* DEBUG */
898 
899     return nssCKFWObject_GetAttributeTypes(fwObject, typeArray, ulCount);
900 }
901 
902 /*
903  * NSSCKFWObject_GetAttributeSize
904  *
905  */
906 NSS_IMPLEMENT CK_ULONG
NSSCKFWObject_GetAttributeSize(NSSCKFWObject * fwObject,CK_ATTRIBUTE_TYPE attribute,CK_RV * pError)907 NSSCKFWObject_GetAttributeSize(
908     NSSCKFWObject *fwObject,
909     CK_ATTRIBUTE_TYPE attribute,
910     CK_RV *pError)
911 {
912 #ifdef DEBUG
913     if (!pError) {
914         return (CK_ULONG)0;
915     }
916 
917     *pError = nssCKFWObject_verifyPointer(fwObject);
918     if (CKR_OK != *pError) {
919         return (CK_ULONG)0;
920     }
921 #endif /* DEBUG */
922 
923     return nssCKFWObject_GetAttributeSize(fwObject, attribute, pError);
924 }
925 
926 /*
927  * NSSCKFWObject_GetAttribute
928  *
929  */
930 NSS_IMPLEMENT NSSItem *
NSSCKFWObject_GetAttribute(NSSCKFWObject * fwObject,CK_ATTRIBUTE_TYPE attribute,NSSItem * itemOpt,NSSArena * arenaOpt,CK_RV * pError)931 NSSCKFWObject_GetAttribute(
932     NSSCKFWObject *fwObject,
933     CK_ATTRIBUTE_TYPE attribute,
934     NSSItem *itemOpt,
935     NSSArena *arenaOpt,
936     CK_RV *pError)
937 {
938 #ifdef DEBUG
939     if (!pError) {
940         return (NSSItem *)NULL;
941     }
942 
943     *pError = nssCKFWObject_verifyPointer(fwObject);
944     if (CKR_OK != *pError) {
945         return (NSSItem *)NULL;
946     }
947 #endif /* DEBUG */
948 
949     return nssCKFWObject_GetAttribute(fwObject, attribute, itemOpt, arenaOpt, pError);
950 }
951 
952 /*
953  * NSSCKFWObject_GetObjectSize
954  *
955  */
956 NSS_IMPLEMENT CK_ULONG
NSSCKFWObject_GetObjectSize(NSSCKFWObject * fwObject,CK_RV * pError)957 NSSCKFWObject_GetObjectSize(
958     NSSCKFWObject *fwObject,
959     CK_RV *pError)
960 {
961 #ifdef DEBUG
962     if (!pError) {
963         return (CK_ULONG)0;
964     }
965 
966     *pError = nssCKFWObject_verifyPointer(fwObject);
967     if (CKR_OK != *pError) {
968         return (CK_ULONG)0;
969     }
970 #endif /* DEBUG */
971 
972     return nssCKFWObject_GetObjectSize(fwObject, pError);
973 }
974