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